MATLAB GUI中优化的标签页

14

我正在MATLAB中的GUI上工作,使用选项卡来组织信息。由于MATLAB GUIDE不支持选项卡,我只创建了多个uipanel并更改它们的'Visible'字段。然而,当每个面板内的控件数量很大时,切换面板需要一些时间。有人知道如何使选项卡切换更快吗?

我提供一个基于选项卡的界面的简单示例。

tab_example_gui.m

% Figure
handles.figure_window = figure(...
    'Units','characters',...
    'Tag','figure_window',...
    'Position',[50 50 80 25],...
    'Name','Tab Example',...
    'DockControls','off',...
    'IntegerHandle','off',...
    'MenuBar','none',...
    'NumberTitle','off',...
    'Resize','off');

% Buttons
handles.tab_panel = uibuttongroup(...
    'Parent',handles.figure_window,...
    'Tag','tab_panel',...
    'Units','characters',...
    'Position',[0 23 80 2],...
    'SelectionChangeFcn',@(hObject,eventdata)tab_example_callback(hObject,eventdata,guidata(hObject)),...
    'BorderType','none');
handles.tab_a = uicontrol(...
    'Parent',handles.tab_panel,...
    'Tag','tab_a',...
    'Units','characters',...
    'Position',[0 0 40 2],...
    'Style','togglebutton',...
    'String','Tab A');
handles.tab_b = uicontrol(...
    'Parent',handles.tab_panel,...
    'Tag','tab_b',...
    'Units','characters',...
    'Position',[40 0 40 2],...
    'Style','togglebutton',...
    'String','Tab B');


% Panel A
handles.panel_a = uipanel(...
    'Parent',handles.figure_window,...
    'Tag','panel_menu',...
    'Units','characters',...
    'Position',[0.1 0 79.8 23],...
    'Visible','On');
handles.panel_a_text = uicontrol(...
    'Parent',handles.panel_a,...
    'Tag','panel_menu_load_id_text',...
    'Units','characters',...
    'Position',[0 0 77 22],...
    'Style','text',...
    'String','This is the tab A');

% Panel B
handles.panel_b = uipanel(...
    'Parent',handles.figure_window,...
    'Tag','panel_menu',...
    'Units','characters',...
    'Position',[0.1 0 79.8 23],...
    'Visible','Off');
handles.panel_b_text = uicontrol(...
    'Parent',handles.panel_b,...
    'Tag','panel_menu_load_id_text',...
    'Units','characters',...
    'Position',[0 0 77 22],...
    'Style','text',...
    'String','This is the tab B');

guidata(handles.figure_window, handles);

tab_example_callback.m

function tab_example_callback(hObject,eventdata,handles)
    switch get(get(hObject,'SelectedObject'),'Tag')
        case 'tab_a', set(handles.panel_a,'Visible','On'); set(handles.panel_b,'Visible','Off');
        case 'tab_b', set(handles.panel_a,'Visible','Off'); set(handles.panel_b,'Visible','On');
    end
    guidata(handles.figure_window, handles);
end

注意:GUI用于在5个选项卡中介绍模拟参数。在每个选项卡中,我大约有15行;每一行都有一个text,一个checkbox和三个edit。对我来说看起来不会显得过于拥挤。此外,我自己进行了布局和回调,并且使用了最少的代码和开销。但是,它仍然具有非常烦人的选项卡转换。


1
我在考虑所有的面板都可以可见,但它们的位置被放置在主图形之外。因此,当选择一个选项卡时,旧选项卡会移开,新选项卡会出现。这样,也许所有的面板都被缓存在GPU内存中,转换速度更快... - tashuhka
1
我认为渲染的默认值已经足够快了,即 'DoubleBuffer','on','Renderer','painters','RendererMode','auto'。还有其他更快的组合吗? - tashuhka
我自己没有尝试过,但也许如果您不使用多个面板,而是只使用一个并更改内容的可见性,可能会有所帮助? - Dennis Jaheruddin
谢谢您的回复。我尝试了一下,但不幸的是它并没有改善情况。我猜问题实际上是要将“可见”属性的更新传播到很多对象中。 - tashuhka
谢谢您的建议。我的代码背后的思路与Yair的代码完全相同。不同之处在于,我的每个面板都有50多个控件,这使得转换变慢。 - tashuhka
显示剩余3条评论
3个回答

3
也许你可以把这些句柄放在一个数组里。这样就不必一个个地查找它们了。这种方法看起来很快,但“快”可能意味着很多东西 :)
我删除了一些属性,以缩短示例...
function test(N) % N is the number of tabs
if nargin == 0
    N = 3;
end

% Figure
handles.figure_window = figure(...
    'Units','characters',...
    'Position',[50 50 80 25]);
% Buttons
handles.tab_panel = uibuttongroup(...
    'Parent',handles.figure_window,...
    'Units','characters',...
    'Position',[0 23 80 2]);

alpha = 'ABCDEFGHIJKLMNOPQRSTUVXYZ';
for i_tab=1:N
    % button
    handles.tabs(i_tab) = uicontrol(...
        'Parent',handles.tab_panel,...
        'Units','characters',...
        'Position',[80/N*(i_tab-1) 0 80/N 2],...
        'Style','togglebutton',...
        'String',['Tab ' alpha(i_tab)]);

    % Panel i
    handles.panels(i_tab) = uipanel(...
        'Parent',handles.figure_window,...
        'Units','characters',...
        'Position',[0.1 0 79.8 23],...
        'Visible','Off');
    handles.panel_a_text = uicontrol(...
        'Parent',handles.panels(i_tab),...
        'Units','characters',...
        'Position',[0 0 77 22],...
        'Style','text',...
        'String',['This is the tab ', alpha(i_tab)]);
end
% set callback for all buttons
set(handles.tabs, 'callback', {@tab_example_callback  handles})
% choose tab 1 as active
set(handles.panels(1), 'Visible','On');
guidata(handles.figure_window, handles);

function tab_example_callback(hObject,eventdata,handles)
% set everything invisible
set(handles.panels,'Visible','Off');
% turn on selected panel
set(handles.panels(handles.tabs == hObject), 'Visible','On');
guidata(handles.figure_window, handles);

这能帮到您吗?

1
这是一个有趣的想法。Profiler实际上显示了稍微更好的计算时间。不幸的是,对于人眼来说并不显著。但是感谢您的时间和代码,它看起来相当不错,并提供了一些改进我的编码的好思路 :) - tashuhka

2

如果您正在创建任何复杂性的GUI,我强烈建议您查看GUI Layout Toolbox,而不要使用GUIDE - 当创建复杂的GUI时,它根本不适合(这不是批评,只是它仅设计用于制作快速、简单的GUI)。

GUI Layout Toolbox使创建专业标准的GUI变得非常容易,并包括选项卡的功能,以及易于调整大小和其他附加小部件等其他功能。

为了解决您在对其他答案的评论中提出的一些问题。GUI Layout Toolbox不使用MATLAB的任何未记录/不支持/隐藏功能。虽然它不是MathWorks的官方产品,但它由MathWorks咨询团队的Ben Tordoff和David Sampson开发,并且在许可下免费提供,这意味着您可以将其用于已部署的产品中。

顺便说一句,您在一条评论中提到每个选项卡都包含大约50个控件。我想知道真正的解决方案是否可能是稍微重新设计您的GUI?当然,您更清楚什么对您的应用程序来说是适当的,但用户一次看到50个控件似乎可能从可用性角度来看是个坏主意,并且会对GUI重绘时间造成困难。


感谢您详细的回复,@Sam Roberts。我看了一下GUI布局工具箱,他们确实做了很棒的工作。在文件CardPanel.m中,包含了处理选项卡可见性的函数showSelectedChild。他们通过将不可见面板向左移动2500像素来改变选项卡的位置。我以前尝试过这个选项,但仍然存在闪烁和冻结问题。 - tashuhka
顺便说一句,我完全同意你的观点,GUIDE对于复杂的GUI并不有用。实际上,我自己编写布局以便对所有模块进行控制。 - tashuhka
3
如果一个面板上有大约50个控件,我认为可能会出现一些闪烁或GUI响应不及时的情况。我之前遇到类似的情况,通过禁用面板的所有子项,进行转换,添加pause(0.5),然后重新启用子项来解决问题。虽然会有一定的延迟,但不会出现闪烁,我发现人们觉得这样更可接受,因为禁用会导致控件变灰,所以他们“知道正在发生什么”。如果情况非常糟糕,您还可以使用一些Java代码将光标临时更改为旋转图标。 - Sam Roberts
谢谢@Sam Roberts。我已经有了pause(0.1)pause()使过渡更加流畅。但是,这只是一个不错的修饰,我很好奇是否有任何实现可以使选项卡转换更快。现在,在简单的桌面应用程序中切换选项卡时等待1秒钟以使所有字段可见似乎过多。 - tashuhka
1
哇,大加一。Matlab的句柄图形缺乏真正的布局控件,这是一个很大的限制。如果我早知道这个工具箱,它会在这些年里为我节省一些真正的头痛。此外,您不应该需要Java来更改光标:如果您在图形句柄上set(h, 'Pointer','watch'),它将更改光标为系统适当的忙指示器,如Mac微调器或Windows沙漏。 - Andrew Janke

1

1
谢谢您的建议。看起来Mathworks正在开发选项卡功能,这太棒了。不幸的是,我不能部署代码,因为它可能在不久的将来无法正常工作。 - tashuhka

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接