- Undocumented Matlab - http://undocumentedmatlab.com -

Setting status-bar text

Posted By Yair Altman On July 23, 2009 | 64 Comments

Most GUI windows nowadays, ranging from web browsers to editors and data-entry windows, have a small status-bar at their bottom. Statusbars are a great way to convey non-critical information to the user, in a non-intrusive manner (without popup windows).
Matlab windows are no exception: they too have status bars which are sometimes used by internal Matlab functions. Unfortunately, there is no documented way to modify Matlab statusbars. In this post I will demonstrate the undocumented way of setting status-bar text, which is probably the most useful use-case. In next week’s post, I will expand this to include more complex customizations, such as dynamic progress-bars or a corner grip.
Note: Users interested in non-intrusive status-bar messages, may also be interested in another non-intrusive messaging mechanism which I have described some months ago: Setting system tray popup messages [1].

Desktop window status-bar

We start with the simplest case of setting the desktop’s statusbar text. We have no further to go than the bottom of Matlab’s own uiopen (see %matlabroot%/toolbox/matlab/uitools/uiopen.m):

dt = javaMethod('getInstance', 'com.mathworks.mde.desk.MLDesktop');
if dt.hasMainFrame
    dt.setStatusText(message);
else
    disp(message);
end

Basically, we try to get the Java reference to the Matlab desktop, see if it has an open window frame and if so then we use its setStatusText() method to display a text message; if not then we display the message in the Command Window (which is probably a non-window console).
Unfortunately, if we place this code in our m-files as-is, our status message will be overridden by Matlab’s “busy” message. A solution for this is to use a one-time (discardable) timer. Another complication is meant for supporting Matlab 6, in which we get the desktop reference differently, and which did not yet have the timer function. The final code now looks like this:

%% Set the status bar text of the Matlab desktop
function setDesktopStatus(statusText)
  % First, get the desktop reference
  try
    desktop = com.mathworks.mde.desk.MLDesktop.getInstance;     % Matlab 7+
  catch
    desktop = com.mathworks.ide.desktop.MLDesktop.getMLDesktop; % Matlab 6
  end
  if desktop.hasMainFrame
    % Schedule a timer to update the status text
    % Note: can't update immediately (will be overridden by Matlab's 'busy' message)
    try
      timerFcn = {@setText,desktop,statusText};
      t = timer('TimerFcn',timerFcn, 'StartDelay',0.05, 'ExecutionMode','singleShot');
      start(t);
    catch
      % Probably an old Matlab version that still doesn't have timer
      desktop.setStatusText(statusText);
    end
  else
    disp(statusText);
  end
%% Utility function used as setDesktopStatus's internal timer's callback
function setText(varargin)
  if nargin == 4  % just in case...
    targetObj  = varargin{3};
    statusText = varargin{4};
    targetObj.setStatusText(statusText);
  else
    % should never happen...
  end

Figure window status-bar

Setting the status-bar text on figure windows is slightly more difficult: getstatus and setstatus appear to be early attempts by Matlab to enable users an access to a figure’s statusbar. In this early attempt, Matlab assumes that the user prepares a text label having a tag of ‘status’. getstatus then returns this label’s string, while setstatus modifies it:

uicontrol('Parent',gcf,'Style','text','Tag','Status');
setstatus(gcf, 'Goodbye');
string = getstatus(gcf);

Unfortunately, nothing prevents the user from placing the label anywhere in the figure, and also from having multiple such labels at once, adding to the confusion. The result is inconsistent with normal windowing practices, and this is probably the reason that MathWorks have grandfathered these functions in Matlab 7.4 (R2007a). It would be much more logical for Matlab to have the statusbar accessible via a figure property, and perhaps this will happen in some future version.
A better, consistent and more flexible access to the figure statusbar can be achieved by using some undocumented Java functions. In a nutshell, we get the figure’s JavaFrame property (which Matlab has warned might be discontinued in some near upcoming release), which is sort of a handle reference to the Java window underlying the Matlab figure window (not exactly but close enough for today). We then travel up and down the JavaFrame window objects hierarchy (use my FindJObj utility on the File Exchange [2] to understand this hierarchy) until we get to the status bar object. We then set its text and make it visible (it’s invisible by default). Here is a trimmed-down version (excluding the necessary sanity checks, exception handling etc.):

% Alternative #1 (hFig = requested figure's handle)
jFrame = get(hFig,'JavaFrame');
jFigPanel = get(jFrame,'FigurePanelContainer');
jRootPane = jFigPanel.getComponent(0).getRootPane;
jRootPane = jRootPane.getTopLevelAncestor;
statusbarObj = jRootPane.getStatusBar;
statusbarObj.setText(statusText);
jRootPane.setStatusBarVisible(1);
% Alternative #2
jFrame = get(hFig,'JavaFrame');
jRootPane = jFrame.fFigureClient.getWindow;
statusbarObj = com.mathworks.mwswing.MJStatusBar;
jRootPane.setStatusBar(statusbarObj);
statusbarObj.setText(statusText);


simple figure status-bar text message
simple figure status-bar text message

StatusBar utility

I’ve created a wrapper function, aptly called statusbar, encapsulating all the above with some additional error checking etc. I have posted statusbar on the MathWorks File Exchange [3]. Readers are encouraged to look at this submission’s source code for examples of statusbar manipulation. Here are several usage examples:


statusbar usage examples (click to see details) [4]
statusbar usage examples (click to see details)

Categories: Desktop, Figure window, GUI, Java, Medium risk of breaking in future versions


64 Comments (Open | Close)

64 Comments To "Setting status-bar text"

#1 Comment By wei On August 6, 2009 @ 16:41

Yair,
This is about uicomponent (e.g. JButton). How does one set button’s Border property so button’s appearance is isolated from PC desktop appearance Windows XP vs. Classic styles?

#2 Comment By Yair Altman On August 6, 2009 @ 16:48

@Wei – First you need to get the underlying Java handle of the Matlab uicomponent (this is done using my FindJObj utility on the File Exchange). Then set the java handle’s Border property as explained here: [11]
Some useful examples: [12]

Yair

#3 Comment By wei On August 6, 2009 @ 17:20

@Yair,
I’m using your uicomponent for such button. there is java component border which, depending on desktop’s appearance, is either com.sun.java.swing.plaf.windows.XPStyle$XPEmptyBorder or javax.swing.plaf.BorderUIResource$CompoundBorderUIResource

Not sure how to proceed to lock onto one style or the other.

#4 Comment By Yair Altman On August 7, 2009 @ 08:48

My uicomponent utility (and similarly Matlab’s javacomponent function) returns the Java reference. This can be used to update the component’s Border property. The default component border is set at creation-time based on the currently-active Look-and-Feel (L&F), but can always be overridden. You can’t pre-lock a property value. But you can modify it immediately following creation, which is essentially the same thing.

Alternately, you can create your component with some specific predefined L&F, regardless of the system’s L&F, as follows:

import javax.swing.UIManager;
originalLnF = UIManager.getLookAndFeel;
UIManager.setLookAndFeel('javax.swing.plaf.metal.MetalLookAndFeel');
   % Create your GUI here...
UIManager.setLookAndFeel(originalLnF);

Here are two official documentation references for the Java L&F system:
[13]
[14]

#5 Comment By wei On August 10, 2009 @ 05:33

@Yair, Thank you for the help. I tried and it worked with second command below:

jButton.setBorder('empty'); %no visible effect
jButton.setBorder([]); 

Another (plaf?) question: after a jbutton is pressed, there is a dotted rectangular line on the button icon indicating the latest focused object. Could this line be removed or set to the same background color so it is invisible?

#6 Comment By Yair Altman On August 19, 2009 @ 08:48

@wei – I believe (not sure) that the dotted line is OS-generated. I do not know of a way to control it with PLAF – you may need to hack some really internal Java/OS function for this…

If you don’t wish the control selection to become visible, perhaps you should simply set the control to be non-focusable or disabled?

#7 Comment By Joan On September 10, 2009 @ 01:05

First of all, congratulations for your excellent site.
I looked for a place where to post this idea, but I didn’t know where to.
I do not like Matlab uitable, and in GUI I use the java table. However, java table is difficult for me to program, specially the Callbacks when someone edits a cell value. Is there a way I could use the table in the ArrayEditor to edit data from a GUI?. The table in the ArrayEditor looks like the java table, and has many features when right-click, and also updates the value of the matrix when I edit a cell value. My idea is to have a button in my main GUI that says “Edit”. When clicked, it opens the ArrayEditor in a separate window. This window should also have buttons Accept, Cancel. In Accept, it collects the data from the ArrayEditor and closes window. When cancel, it simply closes the windows. To put it in a nutshell… is there a way to put the ArrayEditor table in a new figure window, with room left for adding buttons? (I can do all the rest). Thank you very much and congratulations again.

#8 Comment By Yair Altman On September 10, 2009 @ 01:57

Thank Joan
You may find my [15] (on the Matlab File Exchange) useful as a general-purpose sortable Java table. My [16] also uses a Java table, in this case to display the raw data of figure plots. With the knowledge that you have displayed in your question, it should be fairly easy for you to modify the code in these two utilities to fit your purposes.

#9 Comment By Sunny R Billava On October 25, 2010 @ 03:39

can the same thing (Progress bar on status bar) be done for the simulink model editor window’s status bar?

-Sunny

#10 Comment By Yair Altman On October 25, 2010 @ 08:07

@Sunny – I don’t know: I haven’t played with Simulink too much…

#11 Comment By Sandor Toth On November 29, 2010 @ 07:24

I tried statusbar(), but I have a problem when I use it together with tabgroup. After I built my tabs, then I called:

statusbar('My text');

and the tabs disappeared.
Is it some incompatibility issue?

#12 Comment By Yair Altman On November 30, 2010 @ 16:08

@Sandor – the new statusbar simply pushed the figure contents upward a few pixels. Your tabs were probably right at the top of the figure contents, and so they were pushed upward beneath the toolbar and effectively became hidden.

To fix this, simply resize the tab-group’s position property so that its height decreases. For example:

>> set(hTabGroup,'pos',[0,0,1,.95])

#13 Comment By Red Kim On May 29, 2012 @ 02:23

Yair,
I read “Sandor Toth” says. but really I don’t know.
I tried Statusbar with tabgoup.
but tabgroup title bar was up.
and panel is normalized in tabgroup.

But It’s different between it ans with out statusbar.

I can’t say detail about this.
Can you see my script??

/////////////////////////////////////
fh = figure;

htab = uitabgroup(fh);
set(htab, ‘Units’, ‘characters’);
set(htab, ‘position’, [10 10 50 20]);

hhtab = uitab(htab, ‘title’,’Simulation ‘);
hpanel = uipanel(hhtab);

sta_h = statusbar(fh, ‘ ‘);
///////////////////////////////////

#14 Comment By Red Kim On May 29, 2012 @ 02:29

It’s result.
left side is without statusbar.
right side is within statusbar.

#15 Comment By Yair Altman On May 29, 2012 @ 15:12

@Kim – did you read my reply to Sandor? try it…

#16 Comment By Red Kim On May 29, 2012 @ 16:31

Yes. I did it.
I hope you see this picture.

[17]

The picture is with run script.

#17 Comment By Yair Altman On May 30, 2012 @ 14:11

@Kim – I don’t think you read my reply: Your script has to include

set(hTabGroup,'pos',[0,0,1,.95])

if you want the tabs to appear with the statusbar

#18 Comment By Red Kim On May 30, 2012 @ 16:52

I’m Sorry for reply again.
It worked, but it isn’t I want to.

set(hTabGroup,'pos',[0,0,1,.95])

Is it the best way for uitabgoup??
I tried 4 way show uitabgroup within Statusbar.
This picture is result.
[18]

And I also used findjobj() function. uitabgroup has JPanel.
I think the JPanel was pushed by statubar.
So… If I get Handle of JPanel in Matlab, I can move uitabgroup.. maybe..

#19 Comment By Raphael On August 22, 2012 @ 16:41

Is it possible to change the position of the status bar to have it integrated in the GUI ?

#20 Comment By Yair Altman On August 22, 2012 @ 17:12

@Raphael – the status bar is always placed at the bottom of the figure, it cannot be moved. This is the convention in all Windows. Have you ever seen a status bar NOT at the bottom of any window???

#21 Comment By Raphael On August 22, 2012 @ 17:27

I guess I was more thinking about the progress bars in a window, like installation processes.
But I think I found more help regarding this in your javacomponent page

#22 Comment By Yair Altman On August 22, 2012 @ 17:38

There was a recent blog post about progress bars you may find useful, [19]

#23 Comment By Andrei Veldman On May 14, 2014 @ 16:43

Shalom Yair,

A while ago I wrote a little Matlab utility which uses your brilliant “statusbar” utility from the File Exchange. I was getting the handle returned by “statusbar” (which is of type ‘com.mathworks.mwswing.MJStatusBar‘) and then I was setting its ‘ToolTipText‘ and ‘MouseClickedCallback‘ properties. The code looks like this:

set(sb.TextPanel, 'ToolTipText', sToolTip, 'MouseClickedCallback', @TestStatusBarCallback)

This used to work just fine in the past, but in more recent versions of Matlab (e.g. R2014a) I’m getting the following error:

The name 'MouseClickedCallback' is not an accessible property for an instance of class 'com.mathworks.mwswing.MJStatusBar$1'.

I’m guessing they have changed the way one sets up a callback for a mouse click on the status bar. Could you let me know how this is done these days?

Thanks,
Andrei V

#24 Comment By Yair Altman On May 14, 2014 @ 23:35

@Andrei – see my article from last week:
[20]

#25 Comment By Andrei Veldman On May 15, 2014 @ 10:15

Your solution works perfectly!

P.S. I always find coincidences unsettling, like you having already posted a week ago the solution to the problem which I encountered only yesterday! Makes one wonder…

#26 Comment By Luis Camilo On January 11, 2015 @ 19:27

Yair, How can I do that the background is transparent? Thanks.

#27 Comment By Jules-Florent EYA On October 7, 2015 @ 11:53

Thank you Mr. Altman for sharing with us the result of your research.
I have an issue that I do not understand:

In my code I use the two lines that you provided above :

jFrame = get(hFig,'JavaFrame');
jRootPane = jFrame.fFigureClient.getWindow;

Unfortunately I have the following error :

No appropriate method, property, or field fFigureClient for class com.mathworks.hg.peer.HG2FigurePeer.

The version of Matlab that I use is R2014b

#28 Comment By Yair Altman On October 7, 2015 @ 12:17

@Jules – see item #2 here: [21]

#29 Comment By Jules-Florent EYA On October 8, 2015 @ 08:51

Unfortunately Yair,

I tried the following code :

try
   % This works up to R2011a
   jRootPane = jFrame.fFigureClient.getWindow;
catch
   try
      % This works from R2008b and up, up to HG2
      jRootPane = jFrame.fHG1Client.getWindow;
   catch
      % This works in HG2
      jRootPane = jFrame.fHG2Client.getWindow;
   end
end

And the error that is have is now : Attempt to reference field of non-structure array.
It is because JRootPane is empty.

(I use the R2014b Matlab version)

#30 Comment By Yair Altman On October 8, 2015 @ 10:42

this is probably because you have not ensured that the figure window is fully displayed when you reach that code line. Adding drawnow and pause(0.5) should solve this: [22]

#31 Comment By Jules-Florent EYA On October 8, 2015 @ 12:45

Yair, this is the code of my function :

% buildStatusBarObject
function this = buildStatusBarObject(this)
    jFrame = get(this.mainWindow,'JavaFrame');
    if(isempty(jFrame))
        Logger.logError('Retrieved an EMPTY jFrame Object');
    end
    drawnow;
    pause(0.5);
    try
        % This works up to R2011a
        jRootPane = jFrame.fFigureClient.getWindow;
    catch
        try
            % This works from R2008b and up, up to HG2
            jRootPane = jFrame.fHG1Client.getWindow;
        catch
            % This works in HG2
            jRootPane = jFrame.fHG2Client.getWindow;
        end
    end
    statusbarObj = com.mathworks.mwswing.MJStatusBar;
    jRootPane.setStatusBar(statusbarObj);
    statusbarObj.setText('please wait - processing...')
    jRootPane.setStatusBarVisible(true);
end

The jRootPane is still empty, this is why the call ”jRootPane.setStatusBar(statusbarObj);” creates the following error : Attempt to reference field of non-structure array.

#32 Comment By Yair Altman On October 8, 2015 @ 15:00

If the window is not visible then this would be the expected result


Article printed from Undocumented Matlab: http://undocumentedmatlab.com

URL to article: http://undocumentedmatlab.com/articles/setting-status-bar-text

URLs in this post:

[1] Setting system tray popup messages: http://undocumentedmatlab.com/blog/setting-system-tray-popup-messages/

[2] FindJObj utility on the File Exchange: http://www.mathworks.com/matlabcentral/fileexchange/14317

[3] statusbar on the MathWorks File Exchange: http://www.mathworks.com/matlabcentral/fileexchange/14773

[4] Image: http://undocumentedmatlab.com/images/statusbar.png

[5] Setting status-bar components : http://undocumentedmatlab.com/articles/setting-status-bar-components

[6] Setting the Matlab desktop layout programmatically : http://undocumentedmatlab.com/articles/setting-the-matlab-desktop-layout-programmatically

[7] setPrompt – Setting the Matlab Desktop prompt : http://undocumentedmatlab.com/articles/setprompt-setting-matlab-desktop-prompt

[8] Setting listbox mouse actions : http://undocumentedmatlab.com/articles/setting-listbox-mouse-actions

[9] Setting line position in an edit-box uicontrol : http://undocumentedmatlab.com/articles/setting-line-position-in-edit-box-uicontrol

[10] Checking status of warning messages in MEX : http://undocumentedmatlab.com/articles/checking-status-of-warning-messages-in-mex

[11] : http://java.sun.com/docs/books/tutorial/uiswing/components/border.html

[12] : http://www.java2s.com/Code/Java/Swing-JFC/Border.htm

[13] : http://java.sun.com/docs/books/tutorial/uiswing/lookandfeel

[14] : http://java.sun.com/products/jlf/

[15] : http://www.mathworks.com/matlabcentral/fileexchange/14225

[16] : http://www.mathworks.com/matlabcentral/fileexchange/15372

[17] : https://lh6.googleusercontent.com/-z606Gx5OMLw/T8VbXPZQfSI/AAAAAAAAAAk/yw3jRhHjcU8/s912/Result_Img.png

[18] : https://lh3.googleusercontent.com/-lpouA2sLtbo/T8avFMkgQ9I/AAAAAAAAAA0/Eox1IrVovi4/s640/Result.png

[19] : http://blogs.mathworks.com/community/2012/08/13/wait-bars-and-beyond-call-me-when-youre-done/

[20] : http://undocumentedmatlab.com/blog/matlab-callbacks-for-java-events-in-r2014a

[21] : http://undocumentedmatlab.com/blog/hg2-update#observations

[22] : http://undocumentedmatlab.com/blog/matlab-and-the-event-dispatch-thread-edt

Copyright © Yair Altman - Undocumented Matlab. All rights reserved.