Увеличьте частоту обновления элементов пользовательского интерфейса App Designer.

В настоящее время я пытаюсь отобразить данные, которые я получаю через последовательный порт, в приложении дизайнера приложений Matlab. Я страдаю от ужасной частоты обновления линейных датчиков (~ 1 Гц).

Значения датчиков обновляются таймером с фиксированной скоростью, установленным на 30 Гц. Отметка времени в обратном вызове таймера показывает мне, что он вызывается с правильной частотой. Мой компьютер довольно мощный, и диспетчер задач не показывает никаких намеков на высокую нагрузку - на самом деле приложение MATLAB почти вообще не потребляет процессорного времени. На самом деле это не только датчики, но и все элементы пользовательского интерфейса.

Итак, я предполагаю — или, лучше сказать, надеюсь — что должен быть какой-то жесткий предел частоты обновления. Однако официальная документация не дает никаких советов о том, как это изменить.

Моя версия MATLAB — R2016b.

Итак, мой вопрос (ы):

  • Это исправлено с R2017a?

  • Если нет: могу ли я что-то с этим сделать, т.е. возиться со встроенными файлами MATLAB?

Вот пример MCV, демонстрирующий проблему:

classdef testapp < matlab.apps.AppBase

% Properties that correspond to app components
properties (Access = public)
    UIFigure                  matlab.ui.Figure
    andwatchhowthisstartstospinsmoothlyGaugeLabel  matlab.ui.control.Label
    andwatchhowthisstartstospinsmoothlyGauge  matlab.ui.control.SemicircularGauge
    KeepturninghereKnobLabel  matlab.ui.control.Label
    KeepturninghereKnob       matlab.ui.control.Knob
end


properties (Access = private)
    tim_the_timer
    i = 0;
end

methods (Access = private)
    function app = refreshMeter(app, ~,~)
        % display timestamp
        datestr(now,'HH:MM:SS.FFF')

        % update the gauge
        app.andwatchhowthisstartstospinsmoothlyGauge.Value = app.i;
        app.i = app.i + 1;
        if app.i > 100
           app.i = 0;
        end
    end
end


methods (Access = private)

    % Code that executes after component creation
    function startupFcn(app)
       t = timer;
       t.TimerFcn = @app.refreshMeter;
       t.Period = 0.02;
       t.BusyMode = 'drop';
       t.ExecutionMode = 'fixedRate';
       start(t);
       app.tim_the_timer = t;
    end

    % Close request function: UIFigure
    function UIFigureCloseRequest(app, event)
        stop(app.tim_the_timer);
        delete(app.tim_the_timer);
        delete(app);
    end
end

% App initialization and construction
methods (Access = private)

    % Create UIFigure and components
    function createComponents(app)

        % Create UIFigure
        app.UIFigure = uifigure;
        app.UIFigure.Position = [100 100 640 480];
        app.UIFigure.Name = 'UI Figure';
        app.UIFigure.CloseRequestFcn = createCallbackFcn(app, @UIFigureCloseRequest, true);
        setAutoResize(app, app.UIFigure, true)

        % Create andwatchhowthisstartstospinsmoothlyGaugeLabel
        app.andwatchhowthisstartstospinsmoothlyGaugeLabel = uilabel(app.UIFigure);
        app.andwatchhowthisstartstospinsmoothlyGaugeLabel.HorizontalAlignment = 'center';
        app.andwatchhowthisstartstospinsmoothlyGaugeLabel.Position = [275 138 246 15];
        app.andwatchhowthisstartstospinsmoothlyGaugeLabel.Text = '... and watch how this starts to spin smoothly';

        % Create andwatchhowthisstartstospinsmoothlyGauge
        app.andwatchhowthisstartstospinsmoothlyGauge = uigauge(app.UIFigure, 'semicircular');
        app.andwatchhowthisstartstospinsmoothlyGauge.Position = [338 168 120 65];

        % Create KeepturninghereKnobLabel
        app.KeepturninghereKnobLabel = uilabel(app.UIFigure);
        app.KeepturninghereKnobLabel.HorizontalAlignment = 'center';
        app.KeepturninghereKnobLabel.Position = [119 265 112 15];
        app.KeepturninghereKnobLabel.Text = 'Keep turning here...';

        % Create KeepturninghereKnob
        app.KeepturninghereKnob = uiknob(app.UIFigure, 'continuous');
        app.KeepturninghereKnob.Position = [145 314 60 60];
    end
end

methods (Access = public)

    % Construct app
    function app = testapp()

        % Create and configure components
        createComponents(app)

        % Register the app with App Designer
        registerApp(app, app.UIFigure)

        % Execute the startup function
        runStartupFcn(app, @startupFcn)

        if nargout == 0
            clear app
        end
    end

    % Code that executes before app deletion
    function delete(app)

        % Delete UIFigure when app is deleted
        delete(app.UIFigure)
    end
end
end

Редактировать: я заметил, что датчик немедленно обновляется, когда я поворачиваю ручку, ползунок и т. д. Так что каким-то образом возможность более высокой частоты обновления определенно существует... но как включить ее без необходимости сенсорное управление? Обновлен MCV соответственно.


person UnbescholtenerBuerger    schedule 06.07.2017    source источник
comment
Это очень интересная проблема! На самом деле, я думаю, вы столкнулись с механизмом, известным как регулирование. Я заметил, что это срабатывает только тогда, когда обновления слишком часты. В качестве примера: если вы настроите обновление каждые 0,16 с (в моем MATLAB 2017a), движение будет довольно плавным. Я попробую исследовать это дальше....   -  person Dev-iL    schedule 13.08.2017


Ответы (4)


Вы должны иметь возможность принудительно обновить, вызвав функцию drawnow в обратном вызове refreshMeter.

person MrAzzaman    schedule 10.07.2017
comment
Спасибо за Ваш ответ. Как бы вы предложили вызвать drawnow? Простое добавление слова в обратный вызов ничего не дает мне, как и drawnow update, nocallback, expose... - person UnbescholtenerBuerger; 10.07.2017
comment
Теоретически не должно иметь значения, где вы его поместите, если он вызывается регулярно. Я не знаю, почему это не работает для вас, извините. - person MrAzzaman; 11.07.2017

Я бы предложил следующие вещи, чтобы помочь с вашей проблемой:

  1. перейдите по этой очень полезной ссылке, которая предоставляет математическое решение для низкоуровневых графических проблем. Это может быть связано с вашей видеокартой.

  2. следуя предложению @MrAzzamans, drawnow и refreshdata может помочь решить вашу проблему (имейте в виду, что у них разные варианты вызова).

  3. Если вы используете GUIDE, попробуйте перейти на App Designer и посмотрите, решит ли это вашу проблему.

Я столкнулся с подобными проблемами при создании "видео-плеера" в GUIDE, первое предложение решило это для меня.

person yotabyte    schedule 12.07.2017

Поэтому я связался со службой поддержки MathWorks по этому вопросу. К сожалению, это известная проблема, распространенная как в R2016b, так и в 2017a, которая может быть исправлена ​​в будущих выпусках. Служба поддержки также не смогла предоставить мне обходной путь, поэтому пока я просто печатаю данные измерений в командной строке Matlab.

person UnbescholtenerBuerger    schedule 16.07.2017

Я нашел способ заставить события запускать обновление для виджета, для которого drawow не работал: попробуйте sendkeys с возвратом каретки:

h = actxserver('WScript.shell'); h.SendKeys (новая строка);

person alphaquant    schedule 04.12.2018