【问题标题】:guidata not updating in MATLAB GUIguidata 未在 MATLAB GUI 中更新
【发布时间】:2018-04-03 22:18:23
【问题描述】:

我有一个 MATLAB GUI:
1) 一个由activex控制的VLC窗口。
2) 一组单选按钮,用于在特定帧上“注释”视频。

我有工作代码,但我缺少调用注释的函数的输出。此函数Annotate 应将带注释的值替换为先前创建的表final_data。我可以将替换的值显示到控制台,我希望guidata 更新handles,所以我的主函数的输出应该包含一个带有更新值的.final_data 字段。但是,在输出对象上调用 .final_data 会返回空的占位符值。

function Annotate(varargin)

    hFigure = findobj('tag', 'VideoPlay');
    handles = guidata(hFigure);

    % change value of the orther button to 0
    set(handles.hNotAnnotateButton, 'Value', 0);

    mypos = handles.vlc.input.Position; % >> proxy to calculate frame
    behavior = handles.Behavior;  % >>> Tag to be annotated

    % Calculate frame
    myframe = ceil(handles.vlc.input.Time/1000 * handles.frameRate) - 1;

    handles.final_data.behavior(myframe) = behavior;

    display(handles.final_data(myframe, :)) % displays properly

    guidata(handles.hFigure, handles) % not updating handles??
end

以防万一,这是完整的功能

function handles = AnnotateVideo(filepath) 

    % Get some initial data from the video
    filepath = fullfile(filepath);

    % Get file duration

    v = VideoReader(filepath);
    handles.duration = v.Duration;
    handles.frameRate = v.FrameRate;
    delete(v)

    total_frames = ceil(handles.duration * handles.frameRate) - 1;


    %% Make some variables

     handles.final_data.frameID = (1:total_frames)';
     handles.final_data.behavior = strings(total_frames, 1);

     % change format to table
     handles.final_data = struct2table(handles.final_data);

    % Place Holder for behavior


    %% Build the Figure/GUI

    % Video will be kept on handle
    handles.filepath = filepath; 
    % Create figure to receive activex 
    handles.hFigure = figure('position', [50 50 1300 560], ...
                             'menubar', 'none', 'numbertitle', 'off', ...
                             'name', ['Video: ' filepath],...
                             'tag', 'VideoPlay', 'resize', 'on'); 

    % Create play/pause and seek to 0 button 
    handles.hTogglePlayButton = uicontrol(handles.hFigure, ...
                                          'position', [0 540 80 21], ...
                                          'string', 'play/pause', 'callback',...
                                          @TogglePlayPause); 
    handles.hSeekToZeroButton = uicontrol(handles.hFigure, ...
                                          'position', [81 540 80 21], ...
                                          'string', 'begining', 'callback',...
                                          @SeekToZero); 

    handles.hGoToStartFrameButton = uicontrol(handles.hFigure, ...
                                          'position', [161 540 80 21], ...
                                          'string', 'StartFrame', 'callback',...
                                          @SeekToStartFrame);   

    handles.hGoToEndFrameButton = uicontrol(handles.hFigure, ...
                                          'position', [241 540 80 21], ...
                                          'string', 'EndFrame', 'callback',...
                                          @SeekToEndFrame);                                        

%% Annotate button

    handles.hAnnotateButton = uicontrol(handles.hFigure, ...
                                          'Style', 'radiobutton', ...
                                          'position', [980 320 100 41], ...
                                          'String', 'Annotate', 'callback',...
                                          @Annotate);
   handles.hNotAnnotateButton = uicontrol(handles.hFigure, ...
                                       'Style', 'radiobutton', ...
                                       'position', [1100 320 100 41], ...
                                       'String', 'Not-Annotate', ...
                                       'Value', 1, ...
                                       'callback', @NotAnnotate);



%% Make radio buttons for ethogram

handles.radio(1) = uicontrol('Style', 'radiobutton', ...
                           'Callback', @myRadio, ...
                           'Units',    'pixels', ...
                           'Position', [980, 500, 80, 22], ...
                           'String',   'Non-specific', ...
                           'Value',    0);
handles.radio(2) = uicontrol('Style', 'radiobutton', ...
                           'Callback', @myRadio, ...
                           'Units',    'pixels', ...
                           'Position', [980, 480, 80, 22], ...
                           'String',   'Rearing', ...
                           'Value',    0);

handles.radio(3) = uicontrol('Style', 'radiobutton', ...
                           'Callback', @myRadio, ...
                           'Units',    'pixels', ...
                           'Position', [980, 460, 80, 22], ...
                           'String',   'Snif', ...
                           'Value',    0);

handles.radio(4) = uicontrol('Style', 'radiobutton', ...
                           'Callback', @myRadio, ...
                           'Units',    'pixels', ...
                           'Position', [980, 440, 80, 22], ...
                           'String',   'Retrieving', ...
                           'Value',    0);                       

handles.radio(5) = uicontrol('Style', 'radiobutton', ...
                           'Callback', @myRadio, ...
                           'Units',    'pixels', ...
                           'Position', [1100, 500, 80, 22], ...
                           'String',   'Self-Groom', ...
                           'Value',    0); 


%% Activex control for VLC player

    % Create activex control 
    handles.vlc = actxcontrol('VideoLAN.VLCPlugin.2', [0 0 960 540], handles.hFigure); 
    % Format filepath so that VLC can use it


    % Read into vlc

    filepath = ['file://localhost/' filepath]; 


    % Add file to playlist 
    handles.vlc.playlist.add(filepath); 

    % Play file 
    handles.vlc.playlist.play(); 
    % Deinterlace 
    handles.vlc.video.deinterlace.enable('x'); 
    % Go back to begining of file 
    handles.vlc.input.time = 0; 


   % Register an event to trigger when video is being played regularly 
   handles.vlc.registerevent({'MediaPlayerTimeChanged', @MediaPlayerTimeChanged}); 

   % Position changed
   handles.vlc.registerevent({'MediaPlayerPositionChanged', @MediaPlayerPositionChanged});

   % Save handles 
   guidata(handles.hFigure, handles); 


%% Helper functions and button callbacks    


   function MediaPlayerPositionChanged(varargin)
   hFigure = findobj('tag', 'VideoPlay');
   handles = guidata(hFigure);

   % Get position
   handles.mypos = handles.vlc.input.Position;

   % Get frame
   handles.myframe = handles.vlc.input.Time;

   % If position is changing AND annotate button is 'ON' (value == 1)
   % Annotate
   will_annotate = get(handles.hAnnotateButton, 'Value');

   if(will_annotate)
   Annotate
   end

   end

%% Display running time in application title 

    function MediaPlayerTimeChanged(varargin) 
   hFigure = findobj('tag', 'VideoPlay'); 
   handles = guidata(hFigure); 

   myframe = handles.vlc.input.Time;

   set(hFigure, 'name', [handles.filepath ' ; ' num2str(myframe/1000) ' sec.']);

    end

%% Annotate: MAIN 'Looping' Function
% called when position is changed and annotate button

        function Annotate(varargin)

            hFigure = findobj('tag', 'VideoPlay');
            handles = guidata(hFigure);

            % change value of the orther button to 0
            set(handles.hNotAnnotateButton, 'Value', 0);

            mypos = handles.vlc.input.Position;
            behavior = handles.Behavior;

            % Calculate frame
            myframe = ceil(handles.vlc.input.Time/1000 * handles.frameRate) - 1;

            handles.final_data.behavior(myframe) = behavior;

            display(handles.final_data(myframe, :))

            guidata(handles.hFigure, handles)
        end

 %% Not annotate, basic placeholder to not annotate   

    function NotAnnotate(varargin)    
        hFigure = findobj('tag', 'VideoPlay');
        handles = guidata(hFigure);
        % change value of the orther button to 0
        set(handles.hAnnotateButton, 'Value', 0);
    end


    function TogglePlayPause(varargin) 
        % Toggle Play/Pause 
        hFigure = findobj('tag', 'VideoPlay'); 
        handles = guidata(hFigure); 
        handles.vlc.playlist.togglePause(); 
    end

    function SeekToZero(varargin) 
        % Seek to begining of file 
        hFigure = findobj('tag', 'VideoPlay'); 
        handles = guidata(hFigure); 
        handles.vlc.input.Time = 0; 
    end

    function SeekToStartFrame(varargin) 
        % Seek StartFrame of file 
        hFigure = findobj('tag', 'VideoPlay'); 
        handles = guidata(hFigure); 
        handles.vlc.input.Time = StartFrame; 
    end

    function SeekToEndFrame(varargin) 
        % Seek to EndFrame of file 
        hFigure = findobj('tag', 'VideoPlay'); 
        handles = guidata(hFigure); 
        handles.vlc.input.Time = EndFrame;
     end

    function myRadio(RadioH, EventData)
        handles = guidata(RadioH);
        otherRadio = handles.radio(handles.radio ~= RadioH);
        set(otherRadio, 'Value', 0);
        set(handles.hAnnotateButton, 'Value', 0);
        handles.Behavior = RadioH.String;
        sprintf('Switching to...%s', handles.Behavior)
        guidata(handles.hFigure, handles)
    end 


% End of global function


    end

【问题讨论】:

  • 你试过guidata(hFigure, handles)吗?也许handles 的hFigure 字段在某处被覆盖。另外,如果你不使用任何输入参数,为什么你的所有函数中都有varargin?你可以说function Annotate。但更好的是function Annotate(hFigure),调用时可以传递图形句柄。这样您就不需要一直寻找它。
  • @CrisLuengo guidata(hFigure, handles) 产生相同的结果。我有varargin,因为随着事情的发展,我将传递更多的论据,这是对我自己的一个提醒。没错,我可以通过hFigure,但你认为问题与不通过有关吗?
  • 我不知道可能是什么问题。如果我是你,我会在这个函数中设置一个断点,看看hFigure 的值是什么,看看它是否正确设置了guidata,然后看看调用这个函数后还会发生什么。如果您设置断点(您可以在编辑器中执行此操作),您的程序将在该行停止。然后在 MATLAB 命令提示符下,您可以正常执行命令,但您将在函数的工作区中,因此您可以随意检查和修改变量。您可以逐行执行程序。这是弄清楚发生了什么的最好方法。
  • @CrisLuengo 我会尝试这种方法。应该注意的是,display(...) 调用将正确的替换打印到控制台。一定是guidata 没有按预期更新
  • ... 或其他东西稍后将其改回。

标签: matlab video activex matlab-guide


【解决方案1】:

这是因为输出变量永远不会用新的 guidata 更新...

运行你的程序:

handles = AnnotateVideo(<filepath>)

您可以使用(从命令行)更新结构句柄:

handles = guidata(handles.hFigure);

【讨论】:

    【解决方案2】:

    这是更新和答案的混合。我探索了 2 个选项。首先是让一切保持原样,但在运行GUI 之前从控制台运行global output data 并将事情放在那里。第二种方法类似,但我将所有函数取消嵌套到单独的 .m 文件中。我有Annotate 来调用assign('base', 'outputdata', outputdata),而不是全局。这很讨厌,我并不完全喜欢它,但它部分完成了工作。我欢迎任何改进它的建议。

    【讨论】:

      【解决方案3】:

      drawnow 更新图形并处理任何待处理的回调。如果您修改图形对象并希望立即在屏幕上看到更新,请使用此命令。

      drawnow
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2013-12-30
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多