tashuhka
tashuhka

Reputation: 5126

Optimized tabs in MATLAB GUI

I am working in a GUI in MATLAB and I use tabs to organize the information. As the tabs are not supported in MATLAB GUIDE, I just create several uipanels and change their 'Visible' field. However, when the number of controls within each panel is large, it takes some time to switch between panels. Does anybody know a way to make tab switching faster?

I include a simple example of the tab-based interface.

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

Note: The GUI is to introduce parameters for a simulation in 5 tabs. In each tab, I have around 15 rows; and each row has one text, one checkbox and three edits. It does not look overcrowded for me. Besides, I have made the layout and callbacks on my own with the minimum amount of code and overhead. But, it still has very annoying tab transitions.

Upvotes: 14

Views: 7747

Answers (3)

Florian Brucker
Florian Brucker

Reputation: 10355

If you're free to use undocumented features, I suggest using uitab or tabdlg. See this post on undocumentedmatlab.com.

Upvotes: 1

Sam Roberts
Sam Roberts

Reputation: 24127

I strongly recommend that if you are creating a GUI of any complexity, you take a look at GUI Layout Toolbox, and do not use GUIDE - it's just not fit for purpose when creating complex GUIs (that's not a criticism, it's just that it's only designed for making quick, simple GUIs).

GUI Layout Toolbox makes it vastly easier to create professional-standard GUIs, and includes functionality for tabs, as well as much else such as easy resizing and additional widgets.

To address some of the concerns you raised in comments to other answers. GUI Layout Toolbox uses no undocumented / unsupported / hidden features of MATLAB. Although it's not an official MathWorks product, it's developed by Ben Tordoff and David Sampson from MathWorks consulting group, and is freely available under a license that means it's fine for you to use and include in a deployed product.

As a side note, you mention in one comment that your tabs each include about 50 controls. I wonder whether the real solution might be to redesign your GUI a bit? Of course, you would know better then me what is appropriate for your application, but 50 controls visible to the user at once seems like it might be a bad idea from a usability perspective, as well as presenting difficulties for GUI redraw times.

Upvotes: 2

julietKiloRomeo
julietKiloRomeo

Reputation: 178

Maybe if you put the handles in an array. That way you do not have to go through each one of them. This seems fast to me, but 'fast' can mean a lot of things :)

I removed some of the properties to make the example shorter...

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);

Does that help you out?

Upvotes: 3

Related Questions