Using spinners in Matlab GUI

One of the few standard Java Swing controls that does not have any Matlab uicontrol counterpart is JSpinner. JSpinner is basically an editbox with two tiny adjacent up/down buttons. Spinners are similar in functionality to a combo-box (a.k.a. drop-down or pop-up menu), where a user can switch between several pre-selected values. They are often used when the list of possible values is too large to display in a combo-box menu. Like combo-boxes, spinners too can be editable (meaning that the user can type a value in the editbox) or not (the user can only “spin” the value using the up/down buttons).

JSpinner uses an internal data model, similarly to JTree, JTable and other complex controls. The default model is SpinnerNumberModel, which defines a min/max value (unlimited=[] by default) and step-size (1 by default). Additional predefined models are SpinnerListModel (which accepts a cell array of possible string values) and SpinnerDateModel (which defines a date range and step unit).

Here’s a basic code snippet showing how to display a simple numeric spinner for numbers between 20 and 35, with an initial value of 24 and increments of 1:

jModel = javax.swing.SpinnerNumberModel(24,20,35,1);
jSpinner = javax.swing.JSpinner(jModel);
jhSpinner = javacomponent(jSpinner, [10,10,60,20], gcf);

The spinner value can be set using the edit-box or by clicking on one of the tiny arrow buttons, or programmatically by setting the Value property. The spinner object also has related read-only properties NextValue and PreviousValue. The spinner’s model object has the corresponding Value (settable), NextValue (read-only) and PreviousValue (read-only) properties. In addition, the model also has the settable Maximum, Minimum and StepSize properties.

To attach a data-change callback, set the spinner’s StateChangedCallback property.

I have created a small Matlab demo, SpinnerDemo, which demonstrates usage of JSpinner in Matlab figures. Each of the three predefined models (number, list, and date) is presented, and the spinner values are inter-connected via their callbacks. The Matlab code is modeled after the Java code that is used to document JSpinner in the official documentation. Readers are welcome to download this demo from the Matlab File Exchange and reuse its source code.

Java's SpinnerDemo

Java's SpinnerDemo

My Matlab SpinnerDemo

My Matlab SpinnerDemo

As can be seen from the screenshot, SpinnerDemo also demonstrates how to attach a label to a GUI control with an associated accelerator key (Alt-D in the screenshot example, which sets the focus to the Date control).

An internal component in Matlab, namely com.mathworks.mwswing.MJSpinner, extends javax.swing.JSpinner, but in this particular case I cannot see any big advantage of using the internal MJSpinner rather than the standard JSpinner. On the contrary, using JSpinner will likely improve forward compatibility – MathWorks may well change MJSpinner in the future, but it cannot do anything to the standard Swing JSpinner. In other cases, internal Matlab controls do offer significant advantages over the standard Swing controls, but not here it would seem. In any case, the SpinnerDemo utility uses MJSpinner, but you can safely use JSpinner instead (line #86).

The internal Matlab controls are discussed in detail in Chapter 5 of my Matlab-Java book, and MJSpinner is specifically discussed in section 5.2.1.

Another JSpinner derivative is JIDE’s com.jidesoft.grid.SpinnerCellEditor, which can be used as the cell-editor component in tables. An example of this was shown in the article about Advanced JIDE Property Grids (and section 5.7.5 in the book). You may also be interested in the com.jidesoft.combobox.DateSpinnerComboBox, which presents a control that includes both a date-selection combo-box and a spinner (section 5.7.2):

A property grid with spinner control

A property grid with spinner control

JIDE's DateSpinnerComboBox

JIDE's DateSpinnerComboBox

Categories: GUI, Java, Low risk of breaking in future versions

Tags: , ,

Bookmark and SharePrint Print

14 Responses to Using spinners in Matlab GUI

  1. OrO says:

    Great post, very useful. I did not know this function.

  2. ramiro massol says:

    hi Yair
    great jcontrol. Do you happen to know how to force the jspinner to accept only numeric data and at the same time allow to clear the text-box-like field?


    • @Ramiro – good to see you here :-)

      You can force the spinner to accept only numeric data by simply using the SpinnerNumberModel, as I have shown in the article and in my demo application, but then you cannot clear the value because it’s an invalid numeric value. If you think about it, there’s really no reason for a spinner to have no value, because this control is supposed to represent a set of pre-defined values.

  3. Hi, great post!
    I’ve found it very useful and far better (more functional and, of course, better looking) than Spinner (from 2004, I think) I’ve found in official file exchange.

  4. Brittney Marimow says:

    Thank you for the GREAT post. One question, is there a way to place this spinner within a “Parent” box. I am working on a GUI that has 5 different boxes on a single tab and would like to place this spinner in the fourth box.


    • @Brittney – the 3rd (optional) input parameter of the javacomponent function is the parent container handle. It can be the figure handle (default value: current figure or gcf), or a uipanel handle. When you say “box” I assume you mean a uipanel, so simply specify its handle as the 3rd input arg of javacomponent.

      Additional information:

  5. Xiangrui Li says:

    This is very useful, Yair!

    I am trying to find a way to store hFig into a spinner handle, so I can tell which figure in case of multiple figures. Here is code for the test:

    function spinnerTest
    % create a spinner with callback
    jModel = javax.swing.SpinnerNumberModel(1, 1, 9, 1);
    jSpinner = javax.swing.JSpinner(jModel);
    h = javacomponent(jSpinner);
    set(h, 'StateChangedCallback', @spinnerCallBack);
    % add Parent or Ancestor property for matlab gcbo
    schema.prop(h, 'Parent', 'mxArray'); % also tried Ancestor
    h.Parent = gcf;
    %% callback
    function spinnerCallBack(h, evt)
    [hSpinner, hFig] = gcbo; % try to get figure handle
    fprintf('Current value: %g\n', hSpinner.getValue);
    hFig % this is empty with either Parent or Ancestor property added

    I also tried to set datatype as handle, and it seems h.Parent accepts only java handle, not figure/uicontrol handle:

    schema.prop(h, 'Parent', 'handle');
    h.Parent = gcf;
    Parameter must be a handle.

    My current solution is like this in a callback function for both spinner and other uicontrol:

    [h, hFig] = gcbo; % works for matlab uicontrol
    if isempty(hFig) % for java spinner
       hFig = get(h, 'Parent'); % retrieve stored property by schema.prop

    Is there a way to let gcbo return figure handle from java spinner? Octave gcbo uses ‘Parent’, and no idea about Matlab gcbo. Maybe I am too greedy :)


  6. Alain Barraud says:

    hello yair,

    consider the following spinner

    Model = javax.swing.SpinnerNumberModel(125,15,225,.5);
    jSpinner = javax.swing.JSpinner(Model);
    [jhSpinner,hghandle] = javacomponent(jSpinner)
    jhSpinner.Font=java.awt.Font('Serif', 3, 50);

    At this step all is right!

    Now if I want to come back to non bold non italic

    jhSpinner.Font=java.awt.Font('Serif', 0, 50);

    is without any effect!!?? Any idea?

    Another curious point values appear as 140 140,5 141 … and not 140.5 ??


    • @Alain – apparently the JSpinner component creates its internal text-field using the parent control’s Font property value when it is first rendered, and then ignores changes to that parent property value. Instead, you can modify the text-field’s Font property (and its other property values) directly:

      jhSpinner.getEditor.getTextField.setFont(java.awt.Font('Serif', 0, 20));
    • Alain Barraud says:

      Thanks a lot. It works fine. I had a similar problem with Spinner BackgroundColor and ForegroudColor. Now using for exemple

      val = num2cell([0 0.8 0.8]);

      gives the expected result.

      Why a non standard “Text: ‘125,5’” property although the Value property is
      “Value: 1.2550e+02” ?

      ans =

      Is there a way to modify something here?

    • @Alain – see my SpinnerDemo (or read JSpinner‘s documentation) to see how to modify the text formatting.

    • Alain Barraud says:

      I have found the reason. By default the decimal format is local dependent!!
      In France it is , and not .
      Ok I’ll look at your demo.
      However a last point as in your demo, if the user enters a value outside min or max (for example 2030 as year) the spinner is out of use.
      Is there a special callback property to use in order to check this case.


Leave a Reply

Your email address will not be published. Required fields are marked *