Undocumented Matlab
  • SERVICES
    • Consulting
    • Development
    • Training
    • Gallery
    • Testimonials
  • PRODUCTS
    • IQML: IQFeed-Matlab connector
    • IB-Matlab: InteractiveBrokers-Matlab connector
    • EODML: EODHistoricalData-Matlab connector
    • Webinars
  • BOOKS
    • Secrets of MATLAB-Java Programming
    • Accelerating MATLAB Performance
    • MATLAB Succinctly
  • ARTICLES
  • ABOUT
    • Policies
  • CONTACT
  • SERVICES
    • Consulting
    • Development
    • Training
    • Gallery
    • Testimonials
  • PRODUCTS
    • IQML: IQFeed-Matlab connector
    • IB-Matlab: InteractiveBrokers-Matlab connector
    • EODML: EODHistoricalData-Matlab connector
    • Webinars
  • BOOKS
    • Secrets of MATLAB-Java Programming
    • Accelerating MATLAB Performance
    • MATLAB Succinctly
  • ARTICLES
  • ABOUT
    • Policies
  • CONTACT

Figure toolbar components

August 27, 2009 50 Comments

Toolbars are by now a staple of modern GUI design. An unobtrusive list of small icons enables easy access to multiple application actions without requiring large space for textual descriptions. Unfortunately, the built-in documented support for the Matlab toolbars is limited to adding icon buttons via the uipushtool and uitoggletool functions, and new toolbars containing them via the uitoolbar function. In this post I will introduce several additional customizations that rely on undocumented features.
This article will only describe figure toolbars. However, much of the discussion is also relevant to the desktop (Command Window) toolbars and interested users can adapt it accordingly.

Accessing toolbar buttons – undo/redo

Let’s start by adding undo/redo buttons to the existing figure toolbar. I am unclear why such an elementary feature was not included in the default figure toolbar, but this is a fact that can easily be remedied. In another post I describe uiundo, Matlab’s semi-documented support for undo/redo functionality, but for the present let’s assume we already have this functionality set up.
First, let’s prepare our icons, which are basically a green-filled triangle icon and its mirror image:

% Load the Redo icon
icon = fullfile(matlabroot,'/toolbox/matlab/icons/greenarrowicon.gif');
[cdata,map] = imread(icon);
% Convert white pixels into a transparent background
map(find(map(:,1)+map(:,2)+map(:,3)==3)) = NaN;
% Convert into 3D RGB-space
cdataRedo = ind2rgb(cdata,map);
cdataUndo = cdataRedo(:,[16:-1:1],:);

% Load the Redo icon icon = fullfile(matlabroot,'/toolbox/matlab/icons/greenarrowicon.gif'); [cdata,map] = imread(icon); % Convert white pixels into a transparent background map(find(map(:,1)+map(:,2)+map(:,3)==3)) = NaN; % Convert into 3D RGB-space cdataRedo = ind2rgb(cdata,map); cdataUndo = cdataRedo(:,[16:-1:1],:);

Now let’s add these icons to the default figure toolbar:

% Add the icon (and its mirror image = undo) to the latest toolbar
hUndo = uipushtool('cdata',cdataUndo, 'tooltip','undo', 'ClickedCallback','uiundo(gcbf,''execUndo'')');
hRedo = uipushtool('cdata',cdataRedo, 'tooltip','redo', 'ClickedCallback','uiundo(gcbf,''execRedo'')');

% Add the icon (and its mirror image = undo) to the latest toolbar hUndo = uipushtool('cdata',cdataUndo, 'tooltip','undo', 'ClickedCallback','uiundo(gcbf,''execUndo'')'); hRedo = uipushtool('cdata',cdataRedo, 'tooltip','redo', 'ClickedCallback','uiundo(gcbf,''execRedo'')');

Undo/redo buttons
Undo/redo buttons

In the preceding screenshot, since no figure toolbar was previously shown, uipushtool added the undo and redo buttons to a new toolbar. Had the figure toolbar been visible, then the buttons would have been added to its right end. Since undo/redo buttons are normally requested near the left end of toolbars, we need to rearrange the toolbar buttons:

hToolbar = findall(hFig,'tag','FigureToolBar');
%hToolbar = get(hUndo,'Parent');  % an alternative
hButtons = findall(hToolbar);
set(hToolbar,'children',hButtons([4:end-4,2,3,end-3:end]));
set(hUndo,'Separator','on');

hToolbar = findall(hFig,'tag','FigureToolBar'); %hToolbar = get(hUndo,'Parent'); % an alternative hButtons = findall(hToolbar); set(hToolbar,'children',hButtons([4:end-4,2,3,end-3:end])); set(hUndo,'Separator','on');

Undo/redo buttons in their expected positions
Undo/redo buttons in their expected positions

We would normally preserve hUndo and hRedo, and modify their Tooltip and Visible/Enable properties in run-time, based on the availability and name of the latest undo/redo actions:

% Retrieve redo/undo object
undoObj = getappdata(hFig,'uitools_FigureToolManager');
if isempty(undoObj)
   undoObj = uitools.FigureToolManager(hFig);
   setappdata(hFig,'uitools_FigureToolManager',undoObj);
end
% Customize the toolbar buttons
latestUndoAction = undoObj.CommandManager.peekundo;
if isempty(latestUndoAction)
   set(hUndo, 'Tooltip','', 'Enable','off');
else
   tooltipStr = ['undo' latestUndoAction.Name];
   set(hUndo, 'Tooltip',tooltipStr, 'Enable','on');
end

% Retrieve redo/undo object undoObj = getappdata(hFig,'uitools_FigureToolManager'); if isempty(undoObj) undoObj = uitools.FigureToolManager(hFig); setappdata(hFig,'uitools_FigureToolManager',undoObj); end % Customize the toolbar buttons latestUndoAction = undoObj.CommandManager.peekundo; if isempty(latestUndoAction) set(hUndo, 'Tooltip','', 'Enable','off'); else tooltipStr = ['undo' latestUndoAction.Name]; set(hUndo, 'Tooltip',tooltipStr, 'Enable','on'); end

We can easily adapt the method I have just shown to modify/update existing toolbar icons: hiding/disabling them etc. based on the application needs at run-time.

Adding non-button toolbar components – undo dropdown

A more advanced customization is required if we wish to present the undo/redo actions in a drop-down (combo-box). Unfortunately, since Matlab only enables adding uipushtools and uitoggletools to toolbars, we need to use a Java component. The drawback of using such a component is that it is inaccessible via the toolbar’s Children property (implementation of the drop-down callback function is left as an exercise to the reader):

% Add undo dropdown list to the toolbar
jToolbar = get(get(hToolbar,'JavaContainer'),'ComponentPeer');
if ~isempty(jToolbar)
   undoActions = get(undoObj.CommandManager.UndoStack,'Name');
   jCombo = javax.swing.JComboBox(undoActions(end:-1:1));
   set(jCombo, 'ActionPerformedCallback', @myUndoCallbackFcn);
   jToolbar(1).add(jCombo,5); %5th position, after printer icon
   jToolbar(1).repaint;
   jToolbar(1).revalidate;
end
% Drop-down (combo-box) callback function
function myUndoCallbackFcn(hCombo,hEvent)
   itemIndex = get(hCombo,'SelectedIndex');  % 0=topmost item
   itemName  = get(hCombo,'SelectedItem');
   % user processing needs to be placed here
end

% Add undo dropdown list to the toolbar jToolbar = get(get(hToolbar,'JavaContainer'),'ComponentPeer'); if ~isempty(jToolbar) undoActions = get(undoObj.CommandManager.UndoStack,'Name'); jCombo = javax.swing.JComboBox(undoActions(end:-1:1)); set(jCombo, 'ActionPerformedCallback', @myUndoCallbackFcn); jToolbar(1).add(jCombo,5); %5th position, after printer icon jToolbar(1).repaint; jToolbar(1).revalidate; end % Drop-down (combo-box) callback function function myUndoCallbackFcn(hCombo,hEvent) itemIndex = get(hCombo,'SelectedIndex'); % 0=topmost item itemName = get(hCombo,'SelectedItem'); % user processing needs to be placed here end

Undo dropdown list
Undo dropdown list

Note that the javax.swing.JComboBox constructor accepts a cell-array of strings (undoActions in the snippet above). A user-defined dropdownlist might be constructed as follows (also see a related CSSM thread):

...
dropdownStrings = {'here', 'there', 'everywhere'};
jCombo = javax.swing.JComboBox(dropdownStrings);
set(jCombo, 'ActionPerformedCallback', @myUndoCallbackFcn);
jToolbar(1).addSeparator;
jToolbar(1).add(jCombo);  % at end, following a separator mark
jToolbar(1).repaint;
jToolbar(1).revalidate;
...

... dropdownStrings = {'here', 'there', 'everywhere'}; jCombo = javax.swing.JComboBox(dropdownStrings); set(jCombo, 'ActionPerformedCallback', @myUndoCallbackFcn); jToolbar(1).addSeparator; jToolbar(1).add(jCombo); % at end, following a separator mark jToolbar(1).repaint; jToolbar(1).revalidate; ...

A similar approach can be used to add checkboxes, radio-buttons and other non-button controls.
In next week’s post I will describe how the toolbar can be customized using undocumented functionality to achieve a non-default background, a floating toolbar (“palette”) effect and other interesting customizations. If you have any specific toolbar-related request, I’ll be happy to hear in the comments section below.

Related posts:

  1. Toolbar button labels – GUI toolbar button labels can easily be set and customized using underlying Java components. ...
  2. Figure toolbar customizations – Matlab's toolbars can be customized using a combination of undocumented Matlab and Java hacks. This article describes how to customize the Matlab figure toolbar....
  3. Customizing figure toolbar background – Setting the figure toolbar's background color can easily be done using just a tiny bit of Java magic powder. This article explains how. ...
  4. Adding a search box to figure toolbar – An interactive search-box can easily be added to a Matlab figure toolbar for enhanced user experience. ...
  5. Customizing the standard figure toolbar, menubar – The standard figure toolbar and menubar can easily be modified to include a list of recently-used files....
  6. uicontrol side-effect: removing figure toolbar – Matlab's built-in uicontrol function has a side-effect of removing the figure toolbar. This was undocumented until lately. This article describes the side-effect behavior and how to fix it....
GUI Icons Java Semi-documented function Toolbar uitools uiundo
Print Print
« Previous
Next »
50 Responses
  1. Jason McMains August 31, 2009 at 11:28 Reply

    I’m still a little fuzzy on the idea of “memory leaks” so this may be unneccessary, but I usually modify your code like this:

    jToolbar = handle(get(get(hToolbar,'JavaContainer'),'ComponentPeer'),'callbackproperties');
    if ~isempty(jToolbar)
       undoActions = get(undoObj.CommandManager.UndoStack,'Name');
       jCombo = javax.swing.JComboBox(undoActions(end:-1:1));
       jCombo = handle(jCombo,'callbackproperties')
       set(jCombo, 'ActionPerformedCallback', @myUndoCallbackFcn);
       jToolbar(1).add(jCombo,5); %5th position, after printer icon
       jToolbar(1).repaint;
       jToolbar(1).revalidate;
    end

    jToolbar = handle(get(get(hToolbar,'JavaContainer'),'ComponentPeer'),'callbackproperties'); if ~isempty(jToolbar) undoActions = get(undoObj.CommandManager.UndoStack,'Name'); jCombo = javax.swing.JComboBox(undoActions(end:-1:1)); jCombo = handle(jCombo,'callbackproperties') set(jCombo, 'ActionPerformedCallback', @myUndoCallbackFcn); jToolbar(1).add(jCombo,5); %5th position, after printer icon jToolbar(1).repaint; jToolbar(1).revalidate; end

    not sure that getting the handle is necessary to prevent memory leakage, it doesn’t seem to hurt anything though.

  2. Jason McMains October 13, 2009 at 09:26 Reply

    Also I have a few figures that use swing objects, and occasionally doing a uistack or reordering the children of the figure will remove the swing objects in the toolbar. I have done a few work arounds, mostly just avoiding the reorg at all. Just thought I would post that as an issue along with this post so people know about it.

    Thanks Yair as always

    Jason

  3. Dani November 11, 2009 at 05:09 Reply

    Fascinating – I wish Matlab would natively give us access to toolbars and status bars the same way it possible with your “hacks”. I have a question though. If I add a jButton to the toolbar and the status bar they look very different, i.e. the status bar button looks like a nice button but the one in the toolbar lacks the 3D effects. This can be reproduced with the following code:

    %SETUP FIGURE AND FIND TOOLBAR
    hFig= figure;
    hToolbar = findall(gcf,'tag','FigureToolBar');
    jToolbar = get(get(hToolbar,'JavaContainer'),'ComponentPeer');
     
    %ADD BUTTON
    jButton = javax.swing.JButton('Toolbar Button'); 
    jToolbar.add(jButton, 'East');
    jToolbar.revalidate;
    jToolbar.repaint;
     
    %GET STATUS BAR 
    sb = statusbar(hFig, 'Status Bar');
    jb = javax.swing.JButton('Status Button');
    sb.add(jb,'East');
    sb.revalidate;
    sb.repaint;

    %SETUP FIGURE AND FIND TOOLBAR hFig= figure; hToolbar = findall(gcf,'tag','FigureToolBar'); jToolbar = get(get(hToolbar,'JavaContainer'),'ComponentPeer'); %ADD BUTTON jButton = javax.swing.JButton('Toolbar Button'); jToolbar.add(jButton, 'East'); jToolbar.revalidate; jToolbar.repaint; %GET STATUS BAR sb = statusbar(hFig, 'Status Bar'); jb = javax.swing.JButton('Status Button'); sb.add(jb,'East'); sb.revalidate; sb.repaint;

    How can I make the button in the toolbar look ‘nice’ too?

    Another problem is that I have to use your statusbar function since none of the methods described in your status bar post on this site seem to work on my 2009b Matlab, i.e.

    jFrame = get(hFig,'JavaFrame');
    jRootPane = jFrame.fFigureClient.getWindow;
    statusbarObj = com.mathworks.mwswing.MJStatusBar;
    jRootPane.setStatusBar(statusbarObj);
    statusbarObj.setText('test');

    jFrame = get(hFig,'JavaFrame'); jRootPane = jFrame.fFigureClient.getWindow; statusbarObj = com.mathworks.mwswing.MJStatusBar; jRootPane.setStatusBar(statusbarObj); statusbarObj.setText('test');

    gives

    ??? Attempt to reference field of non-structure array.

    ??? Attempt to reference field of non-structure array.

    in

    jRootPane.setStatusBar(statusbarObj);

    jRootPane.setStatusBar(statusbarObj);

    The strange thing is that if I execute line by line in the command window it does work fine….

    • Yair Altman November 11, 2009 at 17:48 Reply

      @Dani –

      1. The toolbar button actually behaves consistently with the other buttons on the toolbar (and your windowing system, for that matter), namely that its border is painted only when you hover your mouse over the button. This is controlled by the JButton’s RolloverEnabled property (which is true by default, and can be turned off if you wish):

      jButton.setRolloverEnabled(0);
      set(jButton,'RolloverEnabled','off');  % an alternative

      jButton.setRolloverEnabled(0); set(jButton,'RolloverEnabled','off'); % an alternative

      To always display a border, you need to override the JButton’s default Border property. Here’s a link to get you started and also sample code: http://java.sun.com/docs/books/tutorial/uiswing/components/border.html

      jBorder = javax.swing.BorderFactory.createRaisedBevelBorder;
      jButton.setBorder(jBorder);

      jBorder = javax.swing.BorderFactory.createRaisedBevelBorder; jButton.setBorder(jBorder);

      2. Yes I know – this issue also occurred in earlier Matlab releases: there’s is a delicate timing issue involved here, which is solved in the statusbar utility but for space considerations was left out of the short code snippets in my posts. When you run the commands in the Command Window one at a time, there is enough delay between commands to solve this problem. Well – that’s what we have utilities for, right?

      Yair

      • Dani November 12, 2009 at 12:48

        @Yair

        this

        jBorder = javax.swing.BorderFactory.createRaisedBevelBorder;
        jButton.setBorder(jBorder);

        jBorder = javax.swing.BorderFactory.createRaisedBevelBorder; jButton.setBorder(jBorder);

        helps, but the status bar button is still a lot ‘nicer’, e.g. rounded corners, 3D color transition effect, larger button relative to text size – what else do I have to invoke to get this effect in the toolbar?

        Dani

  4. Henrik Toft November 11, 2009 at 14:38 Reply

    Collecting most of the pieces of code above I get:

    hFig = figure;
    % Load the Redo icon
    icon = fullfile(matlabroot,'/toolbox/matlab/icons/greenarrowicon.gif');
    [cdata,map] = imread(icon);
     
    % Convert white pixels into a transparent background
    map(find(map(:,1)+map(:,2)+map(:,3)==3)) = NaN;
     
    % Convert into 3D RGB-space
    cdataRedo = ind2rgb(cdata,map);
    cdataUndo = cdataRedo(:,[16:-1:1],:);
     
    % Get handle to figure toolbar
    hToolbar = findall(hFig,'tag','FigureToolBar');
     
    % Add the icon (and its mirror image = undo) to the latest toolbar
    hUndo = uipushtool('parent',hToolbar','cdata',cdataUndo, 'tooltip','undo', 'ClickedCallback','uiundo(gcbf,''execUndo'')');
    hRedo = uipushtool('parent',hToolbar','cdata',cdataRedo, 'tooltip','redo', 'ClickedCallback','uiundo(gcbf,''execRedo'')');
     
    % Retrieve redo/undo object
    undoObj = getappdata(hFig,'uitools_FigureToolManager');
    if isempty(undoObj)
      undoObj = uitools.FigureToolManager(hFig);
      setappdata(hFig,'uitools_FigureToolManager',undoObj);
    end
     
    % Customize the toolbar buttons
    latestUndoAction = undoObj.CommandManager.peekundo;
    if isempty(latestUndoAction)
      set(hUndo, 'Tooltip','', 'Enable','off');
    else
      tooltipStr = ['undo' latestUndoAction.Name];
      set(hUndo, 'Tooltip',tooltipStr, 'Enable','on');
    end

    hFig = figure; % Load the Redo icon icon = fullfile(matlabroot,'/toolbox/matlab/icons/greenarrowicon.gif'); [cdata,map] = imread(icon); % Convert white pixels into a transparent background map(find(map(:,1)+map(:,2)+map(:,3)==3)) = NaN; % Convert into 3D RGB-space cdataRedo = ind2rgb(cdata,map); cdataUndo = cdataRedo(:,[16:-1:1],:); % Get handle to figure toolbar hToolbar = findall(hFig,'tag','FigureToolBar'); % Add the icon (and its mirror image = undo) to the latest toolbar hUndo = uipushtool('parent',hToolbar','cdata',cdataUndo, 'tooltip','undo', 'ClickedCallback','uiundo(gcbf,''execUndo'')'); hRedo = uipushtool('parent',hToolbar','cdata',cdataRedo, 'tooltip','redo', 'ClickedCallback','uiundo(gcbf,''execRedo'')'); % Retrieve redo/undo object undoObj = getappdata(hFig,'uitools_FigureToolManager'); if isempty(undoObj) undoObj = uitools.FigureToolManager(hFig); setappdata(hFig,'uitools_FigureToolManager',undoObj); end % Customize the toolbar buttons latestUndoAction = undoObj.CommandManager.peekundo; if isempty(latestUndoAction) set(hUndo, 'Tooltip','', 'Enable','off'); else tooltipStr = ['undo' latestUndoAction.Name]; set(hUndo, 'Tooltip',tooltipStr, 'Enable','on'); end

    which runs nicely, and adds the two new buttons at the end of the toolbar. However, doing the following:

    % Reposition buttons on toolbar
    hButtons = findall(hToolbar);
    set(hToolbar,'children',hButtons([4:end-4,2,3,end-3:end]));
    set(hUndo,'Separator','on');

    % Reposition buttons on toolbar hButtons = findall(hToolbar); set(hToolbar,'children',hButtons([4:end-4,2,3,end-3:end])); set(hUndo,'Separator','on');

    I get the error:

    ??? Error using ==> set
    Children may only be set to a permutation of itself

    ??? Error using ==> set Children may only be set to a permutation of itself

    Inspecting “hButtons”, it contains 19 handles, but looking at:

    get(hToolbar,'Children')

    get(hToolbar,'Children')

    it only contains 2 (!!!) handles, namely the two buttons that I just added.

    I use MATLAB R2009b, and since I don’t have other versions of MATLAB installed, I don’t know if the is a “new feature” of the latest MATLAB release. I have tried setting “Toolbar” to both “figure” and “auto” but it doesn’t makes any difference.

    Thanks for some inspiring reading 🙂

    Henrik

    • Yair Altman November 11, 2009 at 15:07 Reply

      @Henrik – You got this odd error because the toolbar buttons have hidden handles, which are only exposed to findall but not to findobj or get/set(hToolbar,’Children’). To solve this, temporarily set the desktop to show hidden handles, as follows:

      oldState = get(0,'ShowHiddenHandles');
      set(0,'ShowHiddenHandles','on')
      set(hToolbar,'children',hButtons([4:end-4,2,3,end-3:end]));
      set(0,'ShowHiddenHandles',oldState)

      oldState = get(0,'ShowHiddenHandles'); set(0,'ShowHiddenHandles','on') set(hToolbar,'children',hButtons([4:end-4,2,3,end-3:end])); set(0,'ShowHiddenHandles',oldState)

      – this is actually what findall does, if you look at its source with

      edit('findall')

      edit('findall')

      Yair

      • Henrik Toft November 13, 2009 at 03:35

        @Yair
        @Henrik

        In order for the rearrangement of the buttons to work, in R2009b, it is better to do:

        oldState = get(0,'ShowHiddenHandles');
        set(0,'ShowHiddenHandles','on')
        hButtonsChildren = get(hToolbar,'Children');
        set(0,'ShowHiddenHandles',oldState)

        oldState = get(0,'ShowHiddenHandles'); set(0,'ShowHiddenHandles','on') hButtonsChildren = get(hToolbar,'Children'); set(0,'ShowHiddenHandles',oldState)

        rather than:

        hButtonsFindall = findall(hToolbar);

        hButtonsFindall = findall(hToolbar);

        Since in the first case, only the buttons are found (length(hButtonsChildren) == 18) whereas in the second case also the the handle to the figure toolbar is included AND the undocumented “uitogglesplittool” is divided into two handle elements (length(hButtonsFindall) == 20)!

        Another interesting (although irretating) feature is, that if the following is performed:

        oldState = get(0,'ShowHiddenHandles');
        set(0,'ShowHiddenHandles','on')
        hButtons = get(hToolbar,'Children');
        set(hToolbar,'children',hButtons([3:end-4,1:2,end-3:end]));
        set(0,'ShowHiddenHandles',oldState)

        oldState = get(0,'ShowHiddenHandles'); set(0,'ShowHiddenHandles','on') hButtons = get(hToolbar,'Children'); set(hToolbar,'children',hButtons([3:end-4,1:2,end-3:end])); set(0,'ShowHiddenHandles',oldState)

        the undocumented “uitogglesplittool” which used to the 11th element has now forcefully placed itself as the first element!!! And there it insist on remaining even if I do the following (with “ShowHiddenHandles” = ‘on’):

        set(hToolbar,'children',flipud(hButtons));

        set(hToolbar,'children',flipud(hButtons));

        I don’t konw if “interesting” is the right word 🙂

        Henrik

  5. Dani November 12, 2009 at 13:04 Reply

    @Henrik
    @Yair

    I have another question reqgarding access to the toolbar. If I replace access to the standard figure toolbar

    hToolbar1 = findall(gcf,'tag','FigureToolBar');

    hToolbar1 = findall(gcf,'tag','FigureToolBar');

    with a new toolbar through

    hToolbar2 = uitoolbar;

    hToolbar2 = uitoolbar;

    then the java access to hToolbar2 does not work, i.e.

    jToolbar2 = get(get(hToolbar2,'JavaContainer'),'ComponentPeer');

    jToolbar2 = get(get(hToolbar2,'JavaContainer'),'ComponentPeer');

    returns empty and I can consequently not add ojects such as jButton to it.
    What is the reason for this?

    • Yair Altman November 12, 2009 at 13:12 Reply

      @Dani – read my response above – the answers to your 2 questions are exactly the same answers I gave above:

      1. You need to play around with the Border property. Search the web – there are numerous resources about this issue.
      2. This is a timing issue again. Place a short delay/drawnow between your toolbar creation, your get(…,’JavaContainer’) and your get(…,’ComponentPeer’) to let everything render.

      Yair

  6. danny February 24, 2010 at 18:49 Reply

    Hi,

    I’d like to add a button to the default “figure” Matlab toolbar and have it become part of the button group that contains the zoom/pan etc. buttons. In particular, when the user clicks my button, i want the other buttons in the group to be deselected (btnup function). However, the btnup function requires the “groupid” of the button group; I cannot seem to find this default “id” that Matlab is using for this button group (the group that contains the zoom, pan, etc. buttons).

    Any help would be appreciated, thanks!

    • Yair Altman February 25, 2010 at 02:18 Reply

      @Danny – the btn* set of functions (btnup, btndown, btnpress, btnstate, btnresize and btnicon) work with btngroup. Specifically, you can use btngroup to define the group ID, which is stored in the buttons’ Tag property.

      These functions are obsolete and are not supported (they have a valid help section but no doc page), although for some unknown reason they do not issue an obsolescence warning.

      Although in this blog I frequently advocate the use of undocumented functions, this is NOT the case here. My advise: don’t use btn* functions.

      Nowadays, Matlab uses an altogether different approach to toolbar buttons. There are actually two grouping levels: Low-level grouping logic (zoom in/zoom-out) is done programmatically in zoom.m (near the end of the file), whereas high-level grouping (zoom/pan modes) is done using a ModeManager (which is described in a dedicated article). This mode-manager object can be gotten via the following code:

      >> cbScribe = getappdata(gcf,'ScribeClearModeCallback')
      cbScribe = 
          @set  [1x1 uitools.uimodemanager]  'CurrentMode'  ''
      >> uimodeMgr = cbScribe{2}
      uimodeMgr =
      	uitools.uimodemanager
      >> uimode = get(uimodeMgr,'CurrentMode')
      uimode =
      	uitools.uimode
      >> get(uimode)
                     WindowButtonDownFcn: {2x1 cell}
                       WindowButtonUpFcn: []
                   WindowButtonMotionFcn: {2x1 cell}
                       WindowKeyPressFcn: []
                     WindowKeyReleaseFcn: []
                    WindowScrollWheelFcn: {2x1 cell}
                           KeyReleaseFcn: []
          WindowButtonMotionFcnInterrupt: 0
                      UIControlInterrupt: 0
                             KeyPressFcn: {2x1 cell}
                            ModeStartFcn: {2x1 cell}
                             ModeStopFcn: {2x1 cell}
                         ShowContextMenu: 1
                                    Name: 'Exploration.Zoom'
                               IsOneShot: 0
                          UseContextMenu: 'on'
                            FigureHandle: [1x1 figure]
                        ButtonDownFilter: []
                           UIContextMenu: []
                           ModeStateData: [1x1 struct]

      >> cbScribe = getappdata(gcf,'ScribeClearModeCallback') cbScribe = @set [1x1 uitools.uimodemanager] 'CurrentMode' '' >> uimodeMgr = cbScribe{2} uimodeMgr = uitools.uimodemanager >> uimode = get(uimodeMgr,'CurrentMode') uimode = uitools.uimode >> get(uimode) WindowButtonDownFcn: {2x1 cell} WindowButtonUpFcn: [] WindowButtonMotionFcn: {2x1 cell} WindowKeyPressFcn: [] WindowKeyReleaseFcn: [] WindowScrollWheelFcn: {2x1 cell} KeyReleaseFcn: [] WindowButtonMotionFcnInterrupt: 0 UIControlInterrupt: 0 KeyPressFcn: {2x1 cell} ModeStartFcn: {2x1 cell} ModeStopFcn: {2x1 cell} ShowContextMenu: 1 Name: 'Exploration.Zoom' IsOneShot: 0 UseContextMenu: 'on' FigureHandle: [1x1 figure] ButtonDownFilter: [] UIContextMenu: [] ModeStateData: [1x1 struct]

      • danny February 25, 2010 at 09:48

        Thanks for the advice! I’m trying your code and I got this output (below). Any ideas why it’s returning a null cbScribe value?

        >> plot(1, 1, '.')
        >> cbScribe = getappdata(gcf,'ScribeClearModeCallback') 
        cbScribe =
             []

        >> plot(1, 1, '.') >> cbScribe = getappdata(gcf,'ScribeClearModeCallback') cbScribe = []

      • Yair Altman February 25, 2010 at 10:08

        @danny – this could be because of a different Matlab version/platform than mine, or because your figure toolbar is hidden.

        Try to simply display getappdata(gcf), to check maybe the data is named something other than ‘ScribeClearModeCallback’ on your system.

        Otherwise, tell me your Matlab version and platform and I’ll see if I have anything intelligent to say about this…

      • danny February 25, 2010 at 10:35

        Here’s the output of this command on my version (7.9.0 R2009b):

        >> plot(1, 1)
        >> x = getappdata(gcf)
        x = 
        1x1 struct array with no fields.

        >> plot(1, 1) >> x = getappdata(gcf) x = 1x1 struct array with no fields.

      • Yair Altman February 25, 2010 at 12:28

        @danny – you need to enable one of the modes before this appdata property becomes available. For example, by clicking on one of the buttons or programmatically (e.g., zoom(‘on’) or pan(‘on’)).

      • danny February 25, 2010 at 13:03

        OK, I got it to work, but I don’t see any information that corresponds to a “button group”. I was able to copy and paste some code from a GUIDE output file that works as far as creating a “group” of two buttons that are mutually exclusive (a previously selected button will become deselected if the other button becomes selected). However, I’m unable to add my own “custom” button to this group! Any tips? In the example code snippet below, I’m trying to add a third button “select region” to a group of two other buttons. The first two buttons seem to know about each other but don’t see the third button… I think it has something to do with the “createfcn” called “local_CreateFcn” that I copied from the GUIDE output. Any help is MUCH appreciated!!!!!!!!! 🙂 Thanks!!

            icons = load('icons') ;    
            appdata = [];
            appdata.lastValidTag = 'zoom';
         
            handles.tb = uitoolbar(...
              'Parent',handles.fig,...
              'Tag','zoom',...
              'CreateFcn', {@local_CreateFcn, blanks(0), appdata} );
         
            appdata = [];
            appdata.toolid = 'Exploration.ZoomIn';
            appdata.CallbackInUse = struct('ClickedCallback', 'zoom');
            appdata.lastValidTag = 'zoom';
         
            handles.zoom = uitoggletool(...
              'Parent',handles.tb,...
              'ClickedCallback', 'zoom',...
              'CData',icons.zoomin,...
              'TooltipString','Zoom',...
              'Tag','zoom',...
              'CreateFcn', {@local_CreateFcn, blanks(0), appdata} );
         
            appdata = [];
            appdata.toolid = 'Exploration.Pan';
            appdata.CallbackInUse = struct(...
              'ClickedCallback', 'pan');
            appdata.lastValidTag = 'pan';
         
            handles.pan = uitoggletool(...
              'Parent',handles.tb,...
              'ClickedCallback','pan',...
              'CData',icons.pan,...
              'TooltipString','Pan',...
              'Tag','pan',...
              'CreateFcn', {@local_CreateFcn, blanks(0), appdata} );
         
            A = 1 - [ 0 0 0 0 0 0 0 0 0 0 0 ; 0 0 1 1 1 1 1 1 1 0 0 ; 0 0 0 0 0 1 0 0 0 0 0 ; 0 0 0 0 0 1 0 0 0 0 0 ; 0 0 0 0 0 1 0 0 0 0 0 ; 0 0 0 0 0 1 0 0 0 0 0 ; 0 0 0 0 0 1 0 0 0 0 0 ; 0 0 0 0 0 1 0 0 0 0 0 ; 0 0 0 0 0 1 0 0 0 0 0 ; 0 0 0 0 0 1 0 0 0 0 0 ; 0 0 0 0 0 1 0 0 0 0 0 ; 0 0 0 0 0 1 0 0 0 0 0 ; 0 0 0 0 0 1 0 0 0 0 0 ; 0 0 0 0 0 1 0 0 0 0 0 ; 0 0 0 0 0 1 0 0 0 0 0 ; 0 0 0 0 0 1 0 0 0 0 0 ; 0 0 0 0 0 1 0 0 0 0 0 ; 0 0 1 1 1 1 1 1 1 0 0 ;  0 0 0 0 0 0 0 0 0 0 0] + 1 ;
            m = gray(2) ;
         
            appdata = [];
            appdata.toolid = 'Exploration.SelectRegion';
            appdata.CallbackInUse = struct(...
              'ClickedCallback', '');
            appdata.lastValidTag = 'selreg';
            handles.selreg = uitoggletool(handles.tb, 'TooltipString', 'Select Region', 'OnCallback', @selreg_on, 'OffCallback', @selreg_off, 'CData', ind2rgb(A, m),...
              'CreateFcn', {@local_CreateFcn, blanks(0), appdata}) ;    
          end
         
          function local_CreateFcn(hObject, eventdata, createfcn, appdata)
            if ~isempty(appdata)
              names = fieldnames(appdata);
              for i=1:length(names)
                name = char(names(i));
                setappdata(hObject, name, getfield(appdata,name));
              end
            end
         
            if ~isempty(createfcn)
              if isa(createfcn,'function_handle')
                createfcn(hObject, eventdata);
              else
                eval(createfcn);
              end
            end
          end

        icons = load('icons') ; appdata = []; appdata.lastValidTag = 'zoom'; handles.tb = uitoolbar(... 'Parent',handles.fig,... 'Tag','zoom',... 'CreateFcn', {@local_CreateFcn, blanks(0), appdata} ); appdata = []; appdata.toolid = 'Exploration.ZoomIn'; appdata.CallbackInUse = struct('ClickedCallback', 'zoom'); appdata.lastValidTag = 'zoom'; handles.zoom = uitoggletool(... 'Parent',handles.tb,... 'ClickedCallback', 'zoom',... 'CData',icons.zoomin,... 'TooltipString','Zoom',... 'Tag','zoom',... 'CreateFcn', {@local_CreateFcn, blanks(0), appdata} ); appdata = []; appdata.toolid = 'Exploration.Pan'; appdata.CallbackInUse = struct(... 'ClickedCallback', 'pan'); appdata.lastValidTag = 'pan'; handles.pan = uitoggletool(... 'Parent',handles.tb,... 'ClickedCallback','pan',... 'CData',icons.pan,... 'TooltipString','Pan',... 'Tag','pan',... 'CreateFcn', {@local_CreateFcn, blanks(0), appdata} ); A = 1 - [ 0 0 0 0 0 0 0 0 0 0 0 ; 0 0 1 1 1 1 1 1 1 0 0 ; 0 0 0 0 0 1 0 0 0 0 0 ; 0 0 0 0 0 1 0 0 0 0 0 ; 0 0 0 0 0 1 0 0 0 0 0 ; 0 0 0 0 0 1 0 0 0 0 0 ; 0 0 0 0 0 1 0 0 0 0 0 ; 0 0 0 0 0 1 0 0 0 0 0 ; 0 0 0 0 0 1 0 0 0 0 0 ; 0 0 0 0 0 1 0 0 0 0 0 ; 0 0 0 0 0 1 0 0 0 0 0 ; 0 0 0 0 0 1 0 0 0 0 0 ; 0 0 0 0 0 1 0 0 0 0 0 ; 0 0 0 0 0 1 0 0 0 0 0 ; 0 0 0 0 0 1 0 0 0 0 0 ; 0 0 0 0 0 1 0 0 0 0 0 ; 0 0 0 0 0 1 0 0 0 0 0 ; 0 0 1 1 1 1 1 1 1 0 0 ; 0 0 0 0 0 0 0 0 0 0 0] + 1 ; m = gray(2) ; appdata = []; appdata.toolid = 'Exploration.SelectRegion'; appdata.CallbackInUse = struct(... 'ClickedCallback', ''); appdata.lastValidTag = 'selreg'; handles.selreg = uitoggletool(handles.tb, 'TooltipString', 'Select Region', 'OnCallback', @selreg_on, 'OffCallback', @selreg_off, 'CData', ind2rgb(A, m),... 'CreateFcn', {@local_CreateFcn, blanks(0), appdata}) ; end function local_CreateFcn(hObject, eventdata, createfcn, appdata) if ~isempty(appdata) names = fieldnames(appdata); for i=1:length(names) name = char(names(i)); setappdata(hObject, name, getfield(appdata,name)); end end if ~isempty(createfcn) if isa(createfcn,'function_handle') createfcn(hObject, eventdata); else eval(createfcn); end end end

      • Yair Altman February 25, 2010 at 13:16

        Your first two buttons are zoom and pan, which know of each other and have internal code to handle mutual exclusivity. Your third button is different, so you need to let them know of each other.

        This is more than the space here allows, so if you want to continue discussion, please contact me offline using the email link on the top-right of this page.

  7. Modifying default toolbar/menubar actions | Undocumented Matlab June 2, 2010 at 07:08 Reply

    […] Examples of toolbar customizations were presented in past articles (here and here). A future article will explain how to customize menu […]

  8. uiundo – Matlab’s undocumented undo/redo manager | Undocumented Matlab June 23, 2010 at 03:04 Reply

    […] A couple of months ago, I explained how to customize the figure toolbar. In that article, I used the undocumented uiundo function as a target for the toolbar customization […]

  9. Kesh July 29, 2010 at 07:38 Reply

    Yair,

    Good stuff! I’ve been always wondered about the possibility of adding popupmenu to a uitoolbar. I do have a question though.

    I found if you save a figure (either via GUI or via hgsave) with added JComboBox toolbar component, the JComboBox is not saved. Do you know of any workaround to save java components to a .FIG file?

    Here’s a quick example:

    Let say we created a figure with a popupmenu toolbar:

    fig = figure;
    tb = uitoolbar;
    drawnow
    jToolbar = get(get(tb,'JavaContainer'),'ComponentPeer');
    jCombo = javax.swing.JComboBox({'Test Item 1','Test Item 2'});
    jToolbar.add(jCombo);
    jToolbar.repaint;
    jToolbar.revalidate;
     
    hgsave('test');
    hgload('test');

    fig = figure; tb = uitoolbar; drawnow jToolbar = get(get(tb,'JavaContainer'),'ComponentPeer'); jCombo = javax.swing.JComboBox({'Test Item 1','Test Item 2'}); jToolbar.add(jCombo); jToolbar.repaint; jToolbar.revalidate; hgsave('test'); hgload('test');

    TIA!

    • Yair Altman July 29, 2010 at 09:01 Reply

      @Kesh – good point. Java toolbar customizations are not stored in the saved FIG files. However, you can place your code in the figure’s CreateFcn property, and it will automatically get executed whenever the figure is reloaded from disk:

      codeStr = ['tb=uitoolbar;' ...
                 'drawnow;' ...
                 'jToolbar=get(get(tb,''JavaContainer''),''ComponentPeer'');' ...
                 'jCombo=javax.swing.JComboBox({''Item 1'',''Item 2''});' ...
                 'jToolbar.add(jCombo);' ...
                 'jToolbar.repaint;' ...
                 'jToolbar.revalidate;'];
      set(gcf,'CreateFcn',codeStr)
      hgsave('test');
      eval(codeStr);  % display the new toolbar
       
      hgload('test');

      codeStr = ['tb=uitoolbar;' ... 'drawnow;' ... 'jToolbar=get(get(tb,''JavaContainer''),''ComponentPeer'');' ... 'jCombo=javax.swing.JComboBox({''Item 1'',''Item 2''});' ... 'jToolbar.add(jCombo);' ... 'jToolbar.repaint;' ... 'jToolbar.revalidate;']; set(gcf,'CreateFcn',codeStr) hgsave('test'); eval(codeStr); % display the new toolbar hgload('test');

      • Kesh July 29, 2010 at 15:35

        @Yair – Brilliant solution!

        I have another little annoyance that I’d love to get rid of. It’s a focus-related issue with JComboBox (I suspect it’s more than JcomboBox specific and applies to all Java GUI Components).

        Here’s an example:

        fig = figure;
        set(fig,'WindowKeyPressFcn','disp(''1'')');
        tb = uitoolbar;
        drawnow
        jToolbar = get(get(tb,'JavaContainer'),'ComponentPeer');
        jCombo = javax.swing.JComboBox({'Test Item 1','Test Item 2'});
        jToolbar.add(jCombo);
        jToolbar.repaint;
        jToolbar.revalidate;

        fig = figure; set(fig,'WindowKeyPressFcn','disp(''1'')'); tb = uitoolbar; drawnow jToolbar = get(get(tb,'JavaContainer'),'ComponentPeer'); jCombo = javax.swing.JComboBox({'Test Item 1','Test Item 2'}); jToolbar.add(jCombo); jToolbar.repaint; jToolbar.revalidate;

        WindowsKeyPressFcn is supposed to display “1” in Command Window if a key is pressed anytime when the figure is on top. However, clicking on JComboBox causes WindowsKeyPressFcn to be not called until another part of the figure is clicked.

        I’m guessing that this behavior comes from the fact that the figure window control has been passed on from Matlab to Java when JComboBox gets the focus; thus, Matlab callback events are no longer happening.

        I’m currently using java.awt.Robot.mousePress to force the control back to Matlab. It works, but I’m wondering if there is a better solution (Can we mess with Java Focus Manager?).

        Any ideas?

      • Yair Altman July 29, 2010 at 23:44

        @Kesh – this is actually the expected behavior: the combo-box “consumes” the keyboard event and so the figure window is not aware that an event has occurred. Change your combo-box items to {‘1′,’2′,’3′,’4’} and then click 1,4,3,2 to see that the combo-box moves the selection to the next relevant entry. It is really quite intuitive once you see it.

        BTW, the combo-box keyboard listeners can be removed, but I strongly suggest to NOT do it, since it will also prevent using the arrow keys etc. Moreover, many users will actually expect the regular behavior.

      • Kesh July 30, 2010 at 08:01

        Yair,

        Actually, I thought of that right after I posted yesterday so I did some more testing and found out that the behavior of a Matlab uicontrol popupmenu is indeed what I expect. For example, create a figure with a uicontrol popupmenu and enable both its callback and figure’s keypressfcn:

        uicontrol('style','popupmenu','string',{'1','2','3'},'Callback','disp(''popupmenu callback'')');
        set(gcf,'WindowKeyPressFcn','disp(''windowskeypressfcn'')');

        uicontrol('style','popupmenu','string',{'1','2','3'},'Callback','disp(''popupmenu callback'')'); set(gcf,'WindowKeyPressFcn','disp(''windowskeypressfcn'')');

        Then, when you put focus on the popupmenu and press “1” key, Matlab prints:

        popupmenu callback
        windowskeypressfcn

        popupmenu callback windowskeypressfcn

        I believe I found the fix. Simply the same KeyPress callback function can be assigned to the Java combo-box’s KeyPressCallback.

        Thanks for your tips and great blog!!

  10. Thierry Dalon January 8, 2013 at 03:16 Reply

    Hi Yair&all,
    I can not find out how to have the JComboBox size fitting the elements size. In my application it takes all the place available in the Toolbar.
    Has anyone a clue?
    Thanks
    Thierry

    • Yair Altman January 8, 2013 at 04:10 Reply

      @Thierry – try using a javax.swing.Box component following your JComboBox.

    • Thierry Dalon January 10, 2013 at 04:31 Reply

      @Yair: thanks for the quick reply.
      I’ve found another way by limiting the max width:

      width = jCombo.getPreferredSize().width;
      height = jCombo.getPreferredSize().height;
      jCombo.setMaximumSize(java.awt.Dimension(width,height))

      width = jCombo.getPreferredSize().width; height = jCombo.getPreferredSize().height; jCombo.setMaximumSize(java.awt.Dimension(width,height))

  11. Brian April 23, 2013 at 13:25 Reply

    Hey everybody,
    I have a working JComboBox. 🙂
    However, I made it Editable and I want the drop down list to contain a history of what was typed into the JComboBox.

    I though it would be as easy as calling the ‘addItem’ method in the ‘ActionPerformedCallback’…but its not working.

    I get the error: “Attempt to reference field of non-structure array.” when using

    hCombo.addItem('newitem')

    hCombo.addItem('newitem')

    It doesn’t seem to recognise hCombo as a jComboBox object.

    So I set

    hndl=handle(hCombo)

    hndl=handle(hCombo)

    and then ran

    hndl.addItem('newitem')

    hndl.addItem('newitem')

    and I got this error: “No appropriate method, property, or field addItem for class hg.javax.swing.JComboBox.”

    I find it especially perplexing since I can successfully run

    jCombo.addItem('newitem')

    jCombo.addItem('newitem')

    from outside of the callback, right after I create the JComboBox !?

    Does anybody know how to change/add to the ComboBox item list from the callback?
    Or even just retrieve the entire item list (not just the selected item)?

    Thanks,
    Brian

    p.s. I also get this Warning every time I create the JComboBox: “Warning: Possible deprecated use of set on a Java object with an HG Property ‘ActionPerformedCallback’. ”
    Should I be worried about that?

    • Yair Altman April 23, 2013 at 13:29 Reply

      @Brian – why not pass the jCombo reference directly to your callback function?

      set(jCombo, 'ActionPerformedCallback', {@myCallbackFcn,jCombo});
       
      function myCallbackFcn(hCombo,jEventData,jCombo)
         jCombo.addItem(...)
      end

      set(jCombo, 'ActionPerformedCallback', {@myCallbackFcn,jCombo}); function myCallbackFcn(hCombo,jEventData,jCombo) jCombo.addItem(...) end

    • Brian April 23, 2013 at 14:15 Reply

      Thanks Yair!
      How silly of me, that works great.
      Though I thought jCombo was already being passed to the callback as hCombo.
      Apparently not…so what is hCombo ?
      Thanks again,
      Brian

      • Yair Altman April 23, 2013 at 14:18

        hCombo is an automatically-generated Matlab wrapper for jCombo that is created when the Java event is converted into a Matlab callback. In theory it should enable you access to the entire jCombo functionality, but in practice…

  12. Josh May 23, 2013 at 15:02 Reply

    Hey Yair,

    This is one of the many articles I’ve read on your webpage and I just wanted to stop by and say thanks for providing the exact insight I needed!

    Best,
    Josh

    • Yair Altman May 25, 2013 at 18:45 Reply

      @Josh – I’m glad you like it

  13. mafap August 9, 2013 at 16:27 Reply

    I’m doing a GUI using GUIDE, I have several toolbar buttons, what generates their respective Callbacks but I tried to addapt your scripts to change one of the toolbar icons and it does nothing. What am I doing wrong?
    I’m asking this because import tool in iconeditor doesn’t work (??) [Matlab R2013a]

    • Yair Altman August 10, 2013 at 10:29 Reply

      @Mafap – without looking at your code there is no way of knowing what you did wrong. If you’d like me to look at and fix your code, email me.

    • mafap August 10, 2013 at 12:35 Reply

      for example I have this

       function toolbar_OPT_ClickedCallback(hObject, eventdata, handles)
      % hObject    handle to toolbar_Save_File (see GCBO)
      % eventdata  reserved - to be defined in a future version of MATLAB
      % handles    structure with handles and user data (see GUIDATA)
      %
      % Use a MATLAB icon for the tool
      [X, map] = imread(fullfile(matlabroot,'toolbox','matlab','icons','matlabicon.gif'));
      % Convert indexed image and colormap to truecolor
      icon = ind2rgb(X,map);
      % Create a uipushtool in the toolbar
      hpt = uipushtool(ht,'CData',icon)

      function toolbar_OPT_ClickedCallback(hObject, eventdata, handles) % hObject handle to toolbar_Save_File (see GCBO) % eventdata reserved - to be defined in a future version of MATLAB % handles structure with handles and user data (see GUIDATA) % % Use a MATLAB icon for the tool [X, map] = imread(fullfile(matlabroot,'toolbox','matlab','icons','matlabicon.gif')); % Convert indexed image and colormap to truecolor icon = ind2rgb(X,map); % Create a uipushtool in the toolbar hpt = uipushtool(ht,'CData',icon)

      I wanted this to put some icon in my toolbar but I don’t understant where should I use your scripts because you use them in a programatic environment and I’m using GUIDE.

      Thanks

      • Yair Altman August 10, 2013 at 12:40

        You can place the scripts in the figure’s *_OutputFcn function that is generated by GUIDE.

    • mafap August 12, 2013 at 02:06 Reply

      *_OutputFcn is supposed to return outputs for commmand line and how can I associate this with my created toolbar (OPT icon in this case)?

  14. Daniel September 29, 2013 at 00:36 Reply

    Hello everyone,

    I have a very basic question, but I can’t find the answer. I want to create a Matlab toolbar from zero, with an “open button”, “zoom in” and “zoom out”. How do I do it?!?!
    I create the handle to the Toolbar

    ht=uitoolbar(hFig);

    and then … Where are the standard Toolbar buttons of Matlab documented?!?

    Thanks in advance for all your help!
    Daniel.

    • Yair Altman November 14, 2013 at 18:30 Reply

      @Daniel – I think the easiest solution in your case would be to use the standard Matlab figure toolbar, and simply hide those buttons that you don’t need by setting their Visible property to ‘off’.

      Related: http://undocumentedmatlab.com/blog/customizing-standard-figure-toolbar-menubar/

  15. Michele January 26, 2014 at 09:19 Reply

    Hi

    i’m trying to run a class method trough a uipushbutton clickedcallback call.
    The issue is that I get the error

    Undefined function "mymethod" for input arguments of type 'double'.
    Error while evaluating uipushtool ClickedCallback
    

    I can just run normal function but this is not useful for me

    • Yair Altman January 26, 2014 at 10:03 Reply

      @Michele – you’re probably forgetting that all callbacks automatically recieve the event object handle (a double in the case of HG1) as a first parameter, and eventData as the second parameter.

      The correct way to define such a callback is:

      set(hButton, 'ClickedCallback', @(hButton,e) obj.myMethod(hButton));

      set(hButton, 'ClickedCallback', @(hButton,e) obj.myMethod(hButton));

  16. Kesh August 20, 2014 at 13:24 Reply

    Hey Yair,

    I just bumped into an aggravating issue with Java toolbar components (R2014a) which I don’t think has been brought up on this site.

    The problem: Java based toolbar components disappear when their ancestral figure’s Children property is permuted (including running uistack function). It appears that when figure’s Children is permuted, it invalidates jToolbar object (i.e., ComponentPeer of uitoolbar’s JavaContainer). Here is a minimum working example:

    fig = figure('MenuBar','none');
     
    % create a couple menu items
    h1 = uimenu('parent',fig,'label','&File');
    h2 = uimenu('parent',fig,'label','&Edit');
     
    % add a toolbar
    tb = uitoolbar('Parent',fig);
     
    % add a black uipushtool button
    uipushtool('Parent',tb,'CData',zeros(16,16,3,'uint8'));
    drawnow
     
    % add a JButton on the toolbar
    jToolbar = get(get(tb,'JavaContainer'),'ComponentPeer');
    jtbRun = javax.swing.JButton('JButton');
    jToolbar.add(jtbRun); %1st position
    jToolbar.repaint;
    jToolbar.revalidate;
     
    drawnow
     
    fprintf('jToolbar is valid: %dn',jToolbar.isValid())
    fprintf('jtbRun is valid: %dn',jtbRun.isValid())
     
    h = get(fig,'Children');
    set(fig,'Children',h([1 3 2]))
    drawnow
     
    fprintf('jToolbar is valid: %dn',jToolbar.isValid())
    fprintf('jtbRun is valid: %dn',jtbRun.isValid())

    fig = figure('MenuBar','none'); % create a couple menu items h1 = uimenu('parent',fig,'label','&File'); h2 = uimenu('parent',fig,'label','&Edit'); % add a toolbar tb = uitoolbar('Parent',fig); % add a black uipushtool button uipushtool('Parent',tb,'CData',zeros(16,16,3,'uint8')); drawnow % add a JButton on the toolbar jToolbar = get(get(tb,'JavaContainer'),'ComponentPeer'); jtbRun = javax.swing.JButton('JButton'); jToolbar.add(jtbRun); %1st position jToolbar.repaint; jToolbar.revalidate; drawnow fprintf('jToolbar is valid: %dn',jToolbar.isValid()) fprintf('jtbRun is valid: %dn',jtbRun.isValid()) h = get(fig,'Children'); set(fig,'Children',h([1 3 2])) drawnow fprintf('jToolbar is valid: %dn',jToolbar.isValid()) fprintf('jtbRun is valid: %dn',jtbRun.isValid())

    Do you have any (elegant) workaround for this problem?

    • Yair Altman August 20, 2014 at 13:35 Reply

      @Kesh – You could possibly trap the ComponentHierarchyChanged callback (or something similar) and then re-update the toolbar.

      But I really don’t see this as a major issue: people rarely reorder toolbar components, and when they do it’s mostly when the GUI is first created, so it’s easy to simply update the java stuff after that point, instead of before as you have done.

  17. Kesh August 20, 2014 at 14:36 Reply

    I’m implementing a Matlab application with “dynamic” tabs (adding/deleting tabs with their own menu & toolbar items on the fly.) So, it just happened to be a major issue for me, unfortunately. I’ll look into ComponentHierarchyChanged although I’ve tried several other events/callbacksyet, but so far no success. It would’ve been nice if ObjectBeingDeleted event is present for Java objects…

  18. Sebastian October 21, 2016 at 11:53 Reply

    I’m not sure if this is a common problem. But some of our clients (including me as well) are confused about the behavior of the figure toolbars when docked. In later releases (~R2012 and above) these toolbars are automatically moved to the Matlab ToolStrip when docked into the main window. This makes access to the toolbar harder and much slower, especially if the docking position is at the bottom of the main window.

    Is there a way to avoid this behavior, so that the toolbar stays on its figure window when docked?

    • Yair Altman October 21, 2016 at 11:58 Reply

      @Sebastian – I agree that this is confusing. I am not aware of a way to avoid this.

  19. Santiago September 30, 2021 at 22:12 Reply

    Hi Yair, excellent blog as always.
    I have the doubt if it is possible to use an uitab as a parent of an uimenu or a toolbar?
    I’d like to add one of those options to my uitab.
    Thanks.

    • Yair Altman November 7, 2021 at 12:33 Reply

      @Santiago – AFAIK you cannot parent a Matlab uimenu or uitoolbar to a uitab. However, you can add Java components (in your case, JMenuBar and JToolBar) using the javacomponent function.

      However, IMHO a better alternative would be to set the uitabgroup’s SelectionChangedFcn property to a custom Matlab callback function, that would hide/show various components in the top-level (figure) menu-bar and toolbar based on the currently-selected tab.

Leave a Reply
HTML tags such as <b> or <i> are accepted.
Wrap code fragments inside <pre lang="matlab"> tags, like this:
<pre lang="matlab">
a = magic(3);
disp(sum(a))
</pre>
I reserve the right to edit/delete comments (read the site policies).
Not all comments will be answered. You can always email me (altmany at gmail) for private consulting.

Click here to cancel reply.

Useful links
  •  Email Yair Altman
  •  Subscribe to new posts (feed)
  •  Subscribe to new posts (reader)
  •  Subscribe to comments (feed)
 
Accelerating MATLAB Performance book
Recent Posts

Speeding-up builtin Matlab functions – part 3

Improving graphics interactivity

Interesting Matlab puzzle – analysis

Interesting Matlab puzzle

Undocumented plot marker types

Matlab toolstrip – part 9 (popup figures)

Matlab toolstrip – part 8 (galleries)

Matlab toolstrip – part 7 (selection controls)

Matlab toolstrip – part 6 (complex controls)

Matlab toolstrip – part 5 (icons)

Matlab toolstrip – part 4 (control customization)

Reverting axes controls in figure toolbar

Matlab toolstrip – part 3 (basic customization)

Matlab toolstrip – part 2 (ToolGroup App)

Matlab toolstrip – part 1

Categories
  • Desktop (45)
  • Figure window (59)
  • Guest bloggers (65)
  • GUI (165)
  • Handle graphics (84)
  • Hidden property (42)
  • Icons (15)
  • Java (174)
  • Listeners (22)
  • Memory (16)
  • Mex (13)
  • Presumed future risk (394)
    • High risk of breaking in future versions (100)
    • Low risk of breaking in future versions (160)
    • Medium risk of breaking in future versions (136)
  • Public presentation (6)
  • Semi-documented feature (10)
  • Semi-documented function (35)
  • Stock Matlab function (140)
  • Toolbox (10)
  • UI controls (52)
  • Uncategorized (13)
  • Undocumented feature (217)
  • Undocumented function (37)
Tags
AppDesigner (9) Callbacks (31) Compiler (10) Desktop (38) Donn Shull (10) Editor (8) Figure (19) FindJObj (27) GUI (141) GUIDE (8) Handle graphics (78) HG2 (34) Hidden property (51) HTML (26) Icons (9) Internal component (39) Java (178) JavaFrame (20) JIDE (19) JMI (8) Listener (17) Malcolm Lidierth (8) MCOS (11) Memory (13) Menubar (9) Mex (14) Optical illusion (11) Performance (78) Profiler (9) Pure Matlab (187) schema (7) schema.class (8) schema.prop (18) Semi-documented feature (6) Semi-documented function (33) Toolbar (14) Toolstrip (13) uicontrol (37) uifigure (8) UIInspect (12) uitable (6) uitools (20) Undocumented feature (187) Undocumented function (37) Undocumented property (20)
Recent Comments
Contact us
Captcha image for Custom Contact Forms plugin. You must type the numbers shown in the image
Undocumented Matlab © 2009 - Yair Altman
This website and Octahedron Ltd. are not affiliated with The MathWorks Inc.; MATLAB® is a registered trademark of The MathWorks Inc.
Scroll to top