Non-standard property renderers and editors

Last week, I discussed JIDE’s property table and showed how we can add custom properties and present this table in our Matlab GUI. Today, I will extend the previous week’s example to include more sophisticated renderers and editors.

Cell renderers and editors are the backbone of JTable implementations, JIDE’s property grid included. Each property is associated with a type, and a renderer and an editor may be registered for a type. The cell renderer controls how the property value is displayed, while the editor determines how it is edited. For example, flags (Java Booleans) are often both rendered and edited using a checkbox, but can also use a text renderer with a combo-box editor. PropertyTable automatically assigns a default renderer and editor to each property, based on its type: Flags are assigned a combo-box editor of true/false values, and similarly for other types.

Notice how the EditorContext is used to specify a non-standard renderer/editor for myspinner and mycheckbox: The mylogical flag displays as a string label, while mycheckbox displays as a checkbox; myinteger uses a regular integer editor that accepts whole numbers, while myspinner uses a spinner control to modify the value.

Note that instead of creating an entirely new properties list and table, we could have run last week’s example, modified list and then simply called model.refresh() to update the display.

Also note that Matlab types are automatically converted to Java types, but we must be careful that the results of the conversion should match our setType declaration. The logical value true converts to java.lang.Boolean, but 1 by default would be a double, which is the standard numeric type in Matlab. The int32 wrapper is needed to force a conversion to a java.lang.Integer.

Spinners with indefinite value bounds are seldom useful. The following shows how to register a new editor to restrict values to a fixed range. Remember to unregister the editor when it is no longer used:

Nested properties

Properties can act as a parent node for other properties. A typical example is an object’s dimensions: a parent node value may be edited as a 2-by-1 matrix, but width and height may also be exposed individually. Nested properties are created as regular properties. However, rather than adding them directly to a PropertyTableModel, they are added under a Property instance using its addChild method:

PropertyTableModel accesses properties in a hierarchical naming scheme. This means that the parts of nested properties are separated with a dot (.). In the above example, these two fully-qualified names are dimensions.width and dimensions.height.

Trapping property change events

Sometimes it is desirable to subscribe to the PropertyChange event. This event is fired by PropertyTableModel whenever any property value is updated. To expose Java events to Matlab, we use the two-parameter form of the handle function with the optional CallbackProperties parameter.

The callback function receives two input arguments: The first is the PropertyTableModel object that fired the event, the second is a PropertyChangeEvent object with properties PropertyName, OldValue and NewValue. The PropertyTableModel‘s getProperty(PropertyName) method may be used to fetch the Property instance that has changed.

Callbacks enable property value validation: OldValue can be used to restore the original property value, if NewValue fails to meet some criteria that cannot be programmed into the cell editor. We may, for instance, set the property type to a string; then, in our callback function, use str2num as a validator to try to convert NewValue to a numeric matrix. If the conversion fails, we restore the OldValue:

Hello! Yair, congratulation on your blog, the best Matlab resource I have seen.

I do not know if this tread is too old, but here goes nothing.

I am trying to create a property editor, I found that when I create a dropdown menu and register the editor it does so for every combobox so the dropdown menus are the same for all controls even if at first render the value shown is valid. A small example: (inspired by your examples)

@Yair: I’m trying to validate data input in my propertygrid, using “onPropertyChange” callback. All values of my data is interlinked, so even if a single value can be ok, if the relation between some properties is not the right one, that value is not valid anymore. i.e, let’s suppose I have 3 properties, A, B, C, and always A+B=C. You can set any value to A and B, but if C is not A+B, then you have to change A, B or C to have valid data.

My idea is to highlight wrong values with red background, so i tried to change TableCellRenderer color. My problem is that it changes all cells color and not just the cell(s) i want to highlight. I’m not too good using java, so most probably there’s another way. Maybe i should use different TableCellRenderers for valid/invalid cells? Or do i need to use other java object to handle my propertygrid cells background?

@Jose – the easiest solution is to use HTML colors for cells where you wish to have a non-default color. This can be done by setting the cell’s string to something like '<html><font color="red">123.456'.

Unfortunately, HTML processing in Java table cells is relatively CPU intensive and slow, so it is not advisable for use in numerous cells together, and/or for fast-changing cell values. A better alternative is to use a dedicated TableCellRenderer Java class that enables cell-specific colors. But this requires more advanced Java knowledge and is a subject for a dedicated blog article all on its own (one day I’ll write about it… – it’s somewhere on my TODO list)

I’m trying to mimic part of the Lineseries Property Editor in a custom configuration dialog. This property editor is a great start. I’m looking forward to more details on how to customize the rendering of the controls, such as showing color pickers, line styles, etc.

Alternatively, I would be interested in forgoing the property editor, if I could just directly access the MATLAB controls used to change lineseries properties.

It’s a configuration dialog for a much larger plotting application I’ve built, so I want complete control over the interface. The end users don’t want to see a list of dozens of options, just the basic few properties for changing the line and marker styles.

I’ve downloaded the code, the error does not occur anymore. But also there is no figure displayed!? I am a total beginner with emmbedded java in matlab, I just can’t figure out whats wrong with my system.

@Philip – the component should appear onscreen when the code reaches the javacomponent function call at the bottom of the code snippet. Use the Matlab debugger to discover why it doesn’t reach that point.

I appreciate Propertytables very much and am using it to build a Matlab GUI. Thanks Yair to investigate these functionalities and for sharing your findings with the rest of the world! Of course I cross fingers that the undocumented functionality will not disappear in future Matlab releases 😉

How could I add two buttons into a property cell? I guess there might be a fitting CellEditor. I’d love to see an example on how this is commonly done.

actually I found out that the Jide solution to implement buttons in Propertytable cells turns around the Editor/Renderer HyperLinkTableCellEditorRenderer as demonstrated in the Jide HyperlinkCellDemo. Unfortunately that class does not seem to be included in the Matlab Jide package.

I wonder how Mathworks implemented the buttons in the property inspector.

@Elia – MathWorks probably created a custom renderer that included a JPanel with a JButton. I’m guessing that if you take a look at the JIDE renderers you could relatively easily adapt them to do the same. Alternately, you could perhaps use Matlab’s renderers.

Hello! New query: Did anyone succeed in making a context menu appear related to the PropertyTableModel? I tried to set the UIContextMenu value of the PropertyTableModel value to a uicontextmenu handle, but nothing happens when I right-click anywhere on the Property table.

Hi dear Yair I create a combobox with some item like below: comboBox = javax.swing.JComboBox({‘?’,’?’}); But after load data I have to update combobox with numeric data data = [20.2;30.3;15.22;-5.65;0.365;10.00]; I tried like below: comboBox.add({num2str(A)}); but it is not work… what should I do?

The default column width is 50:50, but I need to set it to 75:25. How can I resize the columns in the property panel? I found that there is autoResizeAllColumns(), but nothing on setting the column widths programmatically.

Like several other posters, I have wanted to dynamically add my own controls to a property grid cell. For example, I want to add a small Save button on each property so a user can permanently save a particular property as a default. Or, I’d like to open a custom dialog box with a button.

I’m having some luck with the following approach (hack). I’m not an expert in Java/Swing or the implications this approach could have on memory or performance in Matlab so please comment if you have any guidance.

As noted by Yair, you’ll need a JPanel to start with so I made a simple cell renderer/editor class in Java

There’s a lot of overhead but I add renderer and editor components for each row. So for one row where I want a combo box and save button I add a renderer panel and editor panel. On the renderer panel I add a JTextField and JButton. On the editor panel I add a JComboBox and JButton. Then register each with CellRendererManager and CellEditorManager respectively.

I managed to get the ‘ValueChangedCallback’ as you suggested. But unfortunately, I only get the actual java ID of the selected component. So, having 8 properties in 3 categories, the ID I get goes from 0 to 10. The components are all stored in a java.util.ArrayList (just like in your example above), which goes from 0 to 7 (for 8 components). Is there a way to get the ‘complete’ list of the property grid, where also the categories are stored in?

Unfortunately, I have no knowledge of java (yet), so I can’t figure it out myself …

Is it possible to perform a ‘reset property value to default’ with jide grid controls?. I was thinking of using .NET PropertyGrid instead which allows this behaviour. Following sample code works great:

But then i don’t know how to embed resulting “.NET form” inside a “matlab figure/panel” (+ Need a workaround to add/remove properties on the fly because .NET grids work from attributes ==> http://stackoverflow.com/q/313822/684399)

I do not know of a way to integrate .NET controls in Matlab figures, but I’m guessing that this may be a solved problem in the Java world. So if you find a way to integrate a .NET control in a Java container, it should be pretty straight-forward to extend this to Matlab figures.

Thanks for your reply. I gave up using a .NET grid to be able to reset edited field to default values (too complex). Anyway, as I dived much into your code, I updated it to accept a ‘callback’ as input argument so as to get more control on how fields are edited (editor type, field description, field name, category, etc…). See ‘uipropedit.m’ and ‘DemoCallback.m’ routines here:

Contribution is not perfect but it’s a first try to get more control on how values are edited. Additionally, the new routine manages for n-dimensional fields (or n-dimensional objects themselves!) using ‘ind2sub’ instead of ‘reshape’ to 3D at max; this is a litle more appealing when editing n-d data.

I’ve been using your inspiring hints smoothly up to R2012b. Since R2013a – and including R2014a – I receive a Java NullPointerException when I click with the mouse pointer on a CheckBoxListCombo in a grid table. Any suggestions on a fix?

I’m trying to make own property inspector. i try step by step on your code. but there are some errors. it’s in combo-box and logical value. making combo-box, logic works well but when i choose other options (ex. your script combo-box spring, summer, fall, winter) i can’t see other options (summer, fall, winter). the error in java , grid . how can i solve the problem..

------error
Exception in thread "AWT-EventQueue-0" java.lang.NullPointerException
at java.lang.reflect.Array.newArray(Native Method)
at java.lang.reflect.Array.newInstance(Array.java:75)
at com.jidesoft.combobox.MultiSelectListExComboBox.convertArrayType(Unknown Source)
at com.jidesoft.combobox.MultiSelectListExComboBox.getSelectedItem(Unknown Source)
at com.jidesoft.combobox.ExComboBox.setConverterContext(Unknown Source)
at com.jidesoft.grid.ExComboBoxCellEditor.getTableCellEditorComponent(Unknown Source)
at javax.swing.JTable.prepareEditor(JTable.java:5778)
at com.jidesoft.grid.JideTable.prepareEditor(Unknown Source)
at com.jidesoft.grid.ContextSensitiveTable.prepareEditor(Unknown Source)
at com.jidesoft.grid.CellStyleTable.prepareEditor(Unknown Source)
at com.jidesoft.grid.CellSpanTable.prepareEditor(Unknown Source)
at com.jidesoft.grid.PropertyTable.prepareEditor(Unknown Source)
at com.jidesoft.grid.JideTable.editCellAt(Unknown Source)
at com.jidesoft.grid.CellSpanTable.editCellAt(Unknown Source)
at javax.swing.plaf.basic.BasicTableUI$Handler.adjustSelection(BasicTableUI.java:1108)
at javax.swing.plaf.basic.BasicTableUI$Handler.mousePressed(BasicTableUI.java:1038)
at javax.swing.plaf.basic.BasicTableUI$MouseInputHandler.mousePressed(BasicTableUI.java:798)
at com.jidesoft.swing.DelegateMouseInputListener.mousePressed(Unknown Source)
at java.awt.AWTEventMulticaster.mousePressed(AWTEventMulticaster.java:280)
at java.awt.Component.processMouseEvent(Component.java:6522)
at javax.swing.JComponent.processMouseEvent(JComponent.java:3324)...

Recent Comments

Yair Altman (1 day 9 hours ago): yes, this post was originally posted in 2011, more than 5 years ago – Matlab has changed a lot since then, including an entirely revised graphics system (HG2). The current...

Andrew (1 day 9 hours ago): I figured it out…actually found it elsewhere but then realized it is mentioned in this original post as well. You can still use getcursorinfo(dcmObject) to get a list of all...

Andrew (1 day 10 hours ago): Hello, Did MATLAB recently change the syntax to this? I am trying to get access to the current list of datacursors programatically, but nothing I have tried seems to work. >>...

Yair Altman (2 days 12 hours ago): @Alex – there is no immediate answer. If you want me to look at your specific code, then email me (altmany at gmail) for a dedicated consulting session.

Yair Altman (2 days 12 hours ago): Perhaps you have an outdated version of export_fig. Try to download the latest version from https://github.com/altmany/exp ort_fig

mimi sam (2 days 13 hours ago): I have “GPL Ghostscript” installed on my PC and I get this : In export_fig at 660 export_fig error. Please ensure: that you are using the latest version of export_fig...

Jaap Nienhuis (3 days 7 hours ago): I frequently make images in Matlab. Is it possible, to render the raster component of the image as a bitmap (image in illustrator) and to render the axes labels etc as vector...

Yair Altman (6 days 9 hours ago): @DavidB + @Guillaume + @TheBlackCat – if I remember correctly, my client wanted the code to continue processing only when the 2 inputs were both vectors, although possibly...

David B (6 days 16 hours ago): @TheBlackCat From the limited information we have available we are assuming the data is a vector. If that is the case then I think something like this code snippet would work nicely...

TheBlackCat (7 days 9 hours ago): It is hard to say without seeing more code. It may very well be that the data can only come in a few formats, so transposing it is the correct thing to do.

Guillaume (7 days 10 hours ago): Well, presumably, the code is operating on vectors, so the alternative could be dataA(:) + dataB(:) But really, the proper alternative would have been to find out why the data...