3

I'm using uitab group in matlab in my GUI. However one limitation of the UItabgroup is absence of enable/disable feature.I tried to use other alternative by using a function from the matlab communnity findjObject

I use the following way to do that using the above function.

jtabgroup=findjobj(tabgroup);
jtabgroup.setEnableAt(false); % also I tried turning enable off for 
% for individual tabs using setEnabledAt(1,0) 

and I get the following error

Undefined function 'setEnabled' for input arguments of type 'handle.handle'.

Can someone help me with this issue or suggest me some alternative way of enable/disable tabs.

5
  • You have two differents class: uitab and findjobj but you mix the function of those class ! findjobj simply don't support the function setEnableAt Commented May 25, 2016 at 9:07
  • you can try : methodsview(jtabgroup) in order to display all the methods availables Commented May 25, 2016 at 9:10
  • I found few people who have implemented the method using findjobject . However I'm unsure the methods adopted by them. Commented May 25, 2016 at 12:06
  • how about the 'visible' property? Commented May 25, 2016 at 12:39
  • I want the tabs to be visible and the user shouldn't have access to it until another key is pressed. Commented May 25, 2016 at 12:55

5 Answers 5

1

You can, and should, use a wonderful GUI Layout Toolbox instead of uitab. It allows you to selectively disable tabs out of the box, not to mention the vast array of other useful features. There are two submissions on FEX, one for HG1 (uiextras package) and another for HG2 (uix package, with backward-compatible uiextras interface).

Here's HG2 example. You need to set TabEnables property to an array of 'on'/'off' values, one per tab (not the most user-friendly API, but hey, that's far better than anything else out there).

f = figure();
p = uix.TabPanel('Parent', f,'Padding', 5);
uicontrol('Style', 'frame', 'Parent', p, 'Background', 'r');
uicontrol('Style', 'frame', 'Parent', p, 'Background', [.8 .8 .8]);
uicontrol('Style', 'frame', 'Parent', p, 'Background', 'g');
p.TabTitles = {'Red', 'Gray', 'Green'};
p.Selection = 2;
p.TabEnables = {'on','on','off'};

enter image description here

Another suggestion would be to resort to pure java solutions. That obviously assumes you can only place java components inside your tabs, but pretty much any Matlab UI component, apart from axes, can be easily replaced with better-behaving and better-looking java counterpart.

Sign up to request clarification or add additional context in comments.

3 Comments

Thanks for your answer. I think this could be a good option if I'm not much concerned about the user-friendly API.
@PBCR, to be fair, the API for uicontrol is even worse. Unless you're going to use pure java, that's the best you can get. And they look more "professional" to my taste.
True agreed. I'm gonna accept your answer, since it did help me in designing another GUI. Sometimes, I get annoyed by the limitations of the uicontrols in matlab
1

An easier solution that works for me - I have a method that recursively looks for components in a tab and sets the enable (if can be enabled). Note: this doesn't enable an entire tab but rather the contents. For the best graphical look I ignore certain elements

function setEnableWithChildren(app, component, value) % Recursively set enable status for all items

if isa(component, 'matlab.ui.control.Label') || isa(component, 'matlab.ui.control.Lamp')
    return % Don't enable labels, etc.
end

if isprop(component, 'Enable')
    if isa(component, 'matlab.ui.control.Table')
        if value
            component.Enable = 'on'; % Table uses on/off
        else
            component.Enable = 'off';
        end
    else
        component.Enable = value;
    end
end

if isprop(component, 'Children')
    children = allchild(component);
else
    children = [];
end
for child = reshape(children, 1, [])
    app.setEnableWithChildren(child, value);
end

end

Comments

1

A somewhat sketchy but effective solution that uses only MATLAB components is to use a textless, colorless uilabel as a mask, placed over your tab. If the label is Visible, the tab will be unselectable since you can't click through the label. If the label Visible property is "off" you can select the tab. This avoids the issue of changing tabs, running a callback, then changing back.

Comments

1

If you're using the App Designer or otherwise working with the web-based MATLAB GUI, the JavaFrame UI stuff has no effect and so findjobj based solutions for disabling tabs won't work.

There's a similar script to findjobj for the web-based GUI called mlapptools. In broad strokes, you can use this to find the <div>s that have the tab class and contain a span with the mwTabHeader class, and then use the CSS pointer-events property to disallow input on the tab. This locks the user out of clicking the tab, and hence switching it and activating any callback functions. I had trouble using mlapptools to navigate the HTML tree, so I ended up using the Text Analytics toolbox to do this instead.

% Get the HTML code that makes the figure and parse it to look for <div>s
tabHTML = jsondecode(app.win.executeJS('[...document.querySelectorAll("div.tab")].map(div => ({ innerHTML: div.querySelector("span.mwTabLabel").innerHTML, widgetid: div.getAttribute("widgetid") }));'));

% Get all of the current tabs titles
tabs = {app.TabGroup.Children.Title};
app.tabIDs = cell(size(tabs));

% For each DIV, match it up to a tab and extract the widgetid
for ii=1:length(tabHTML)
    for jj=1:length(tabs)
        if strcmp(tabHTML(ii).innerHTML, tabs{jj})
            fprintf('match %s with %s\n', tabHTML(ii).innerHTML, tabs{jj})
            app.tabIDs{jj} = tabHTML(ii).widgetid;
            break
        end
    end
end

fprintf('Locking tabs...\n');
win = mlapptools.getWebWindow(hUIFigure);
currentTab = find(tabgroup.SelectedTab == tabgroup.Children);
for ii=1:length(tabIDs)
    if ii ~= currentTab
        % execute dojo queries for each tab to set the style
        % note the DOM format CSS
        win.executeJS(sprintf('dojo.style(dojo.query("[%s = ''%s'']")[0], "%s", "%s")', ...
            'widgetid', tabIDs{ii}, ...
            'pointerEvents', 'none'));
        win.executeJS(sprintf('dojo.style(dojo.query("[%s = ''%s'']")[0], "%s", "%s")', ...
            'widgetid', tabIDs{ii}, ...
            'color', 'grey'));
    end
end

fprintf('Unlocking tabs...\n');
for ii=1:length(tabIDs)
    win.executeJS(sprintf('dojo.style(dojo.query("[%s = ''%s'']")[0], "%s", "%s")', ...
        'widgetid', tabIDs{ii}, ...
        'pointerEvents', 'auto'));
    win.executeJS(sprintf('dojo.style(dojo.query("[%s = ''%s'']")[0], "%s", "%s")', ...
        'widgetid', tabIDs{ii}, ...
        'color', 'black'));
end

Old version:

This old version of finding out the tabIDs requires the Text Analytics Toolbox, but is easier to read:

% Get the HTML code that makes the figure and parse it to look for <div>s
page = mlapptools.getHTML(hUIFigure);
page = strrep(page, '\n', newline); % I had issues with HTML parsing without
page = strrep(page, '\"', '"'); % these additional substitutions
tree = htmlTree(page);
subtrees = findElement(tree, 'div');

% Get all of the current tabs titles
tabs = {tabgroup.Children.Title};
tabIDs = cell(size(tabs));

% For each DIV, match it up to a tab and extract the widgetid
for ii=1:length(subtrees)
    if contains(getAttribute(subtrees(ii), 'class'), 'tab') && ...
            contains(sprintf('%s', subtrees(ii)), 'mwTabHeader')
        for jj=1:length(tabs)
            if strcmp(strtrim(extractHTMLText(subtrees(ii))), tabs{jj})
                tabIDs{jj} = char(getAttribute(subtrees(ii), 'widgetid'));
                break
            end
        end
    end
end

Comments

0

Unfortunately, as reported in the comments, the uitab does not have a enable property.

This is the list of the iutab object:

 BackgroundColor
    BeingDeleted
      BusyAction
   ButtonDownFcn
        Children
       CreateFcn
       DeleteFcn
 ForegroundColor
HandleVisibility
   Interruptible
          Parent
        Position
  SizeChangedFcn
             Tag
           Title
   TooltipString
            Type
   UIContextMenu
           Units
        UserData

A possible workaround could be to enable / disable the uicontrols belonging to the uitab.

You can get the list of uicontrols of a uitab since they handles are stored in the children property.

Once you have the handles, you can set their enable property to either on or off.

In the following code:

  • a uitabgroupis created including two iutab
  • in each iutab some uicontrols are added with the initial enable status set to 'off`
  • in the figure, two checkbox are added to enable / disable the uicontrols of the two uitab

The functin that get the hanles and enable / disable the uicontrols has been directly written as callbak of the checkbox

% Create a Figure
f = figure;
% Add a uitabgroup
tabgp = uitabgroup(f,'Position',[.05 .05 .3 .8]);
% Add two uitab
tab1 = uitab(tabgp,'Title','Tab #1');
tab2 = uitab(tabgp,'Title','Tab #2');
% Add some uicontrols to the first uitab (initial status = disabled)
% Add a Pushbutton
uicontrol('parent',tab1,'style','pushbutton','unit','normalized', ...
   'position',[.1 .1 .3 .1],'string','OK','enable','off')
% Add a checkbox
uicontrol('parent',tab1,'style','checkbox','unit','normalized', ...
   'position',[.1 .3 .6 .1],'string','Checkbox #1','enable','off')
% Add a radiobutton
uicontrol('parent',tab1,'style','radio','unit','normalized', ...
   'position',[.1 .6 .5 .1],'string','Radio #1','enable','off')
% Add another radiobutton
uicontrol('parent',tab1,'style','radio','unit','normalized', ...
   'position',[.1 .5 .5 .1],'string','Radio #2','enable','off')

% Add some uicontrols to the first uitab
% Add a Pushbutton
uicontrol('parent',tab2,'style','pushbutton','unit','normalized', ...
   'position',[.1 .1 .3 .1],'string','OK','enable','off')
% Add a checkbox
uicontrol('parent',tab2,'style','checkbox','unit','normalized', ...
   'position',[.1 .3 .6 .1],'string','Checkbox #1','enable','off')
% Add a radiobutton
uicontrol('parent',tab2,'style','radio','unit','normalized', ...
   'position',[.1 .6 .5 .1],'string','Radio #1','enable','off')
% Add another radiobutton
uicontrol('parent',tab2,'style','radio','unit','normalized', ...
   'position',[.1 .5 .5 .1],'string','Radio #2','enable','off')
% Add two checkbox to the Figure to enable / disable the uicontrols in the
% uitab
uicontrol('parent',f,'style','checkbox','unit','normalized', ...
   'position',[.4 .3 .6 .1],'string','Enable Tab 1 uicontrols', ...
   'callback','tab1_c=get(tab1,''children'');e_d=''off'';if(get(gcbo,''value'') == 1) e_d=''on''; end;set(tab1_c(:),''Enable'',e_d)')
uicontrol('parent',f,'style','checkbox','unit','normalized', ...
   'position',[.4 .4 .6 .1],'string','Enable Tab 2 uicontrols', ...
   'callback','tab2_c=get(tab2,''children'');e_d=''off'';if(get(gcbo,''value'') == 1) e_d=''on''; end;set(tab2_c(:),''Enable'',e_d)')

enter image description here

Hope this helps.

Qapla'

1 Comment

Thanks for your answer. I did already think of this procedure. But I want to completely disable access to tabs. I mean the user can't even click on the tabs.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.