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

propertiesGUI

Posted By Yair Altman On January 30, 2013 | 34 Comments

Last week I presented a detailed explanation of the uiinspect utility [1], which displays a GUI listing all the properties, callbacks and internal methods of an inspected object. Something like Matlab’s inspect tool on steroids. I explained that uiinspect uses com.mathworks.mlwidgets.inspector.PropertyView, which in turn uses JIDE’s PropertyTable [2]. PropertyView automatically extracts the inspected object’s properties and displays them using a corresponding renderer in the PropertyTable.

propertiesGUI demo
propertiesGUI demo

We often need to present a non-object Matlab construct. For example, it is very common to store an application’s configuration properties in a struct (using Matlab objects is often impractical and unwarranted) — it would be very useful to present this configuration dynamically, without having to programmatically scan all struct fields and build a dedicated GUI table. Unfortunately, PropertyView cannot automatically retrospect Matlab structs, which is the reason that the built-in inspect function fails for such objects. In the general case, we may wish to present a PropertyTable using row-specific renderers and editors, when we have such an un-inspectable object (struct, cell array etc.), or even for a dynamically-created table of properties that is not stored in any single object.
Another limitation of PropertyView is that it immediately assigns updated property values to the inspected object, without allowing any sanity checks to be conducted on the new values, and without enabling the user to cancel property changes.
Last but not least, PropertyView does not enable users to easily modify the way that certain properties are presented. Boolean properties (true/false) always use a checkbox cell-renderer/editor, while we may wish to display a string (on/off) or combo-box instead.
In short, PropertyView is great unless you want to customize stuff, or do something slightly out-of-the-ordinary.
Enter propertiesGUI, the subject of today’s article.

The propertiesGUI utility

propertiesGUI, which can be downloaded [3] from the Matlab File Exchange, presents a generic solution to this problem. propertiesGUI is based on Levente Hunyadi’s articles here [4] back in 2010, and on his “Property grid” utility [5] on the File Exchange.
propertiesGUI expects the following syntax:

[hPropsPane, parameters] = propertiesGUI(hParent, parameters)

where:

  • hParent (input) is an optional handle of a parent GUI container (figure/uipanel/uitab) in which the properties table will appear. If missing or empty or 0, the table will be shown in a new modal dialog window; otherwise it will be embedded in the parent container.
  • parameters (input) is an optional struct or object with data fields. The fields are processed separately to determine their corresponding cell renderer and editor. If parameters is not specified, then the global test_data will be used. If test_data is also empty, then a demo of several different data types will be used.
  • hPropsPane (output) is the handle of the generated properties panel widget, which can be customized to display field descriptions, toolbar, etc.
  • parameters (output) is the resulting (possibly-updated) parameters struct. Naturally, this is only relevant in case of a modal dialog.

When passing the properties in an input parameters struct, propertiesGUI automatically inspects each struct field and assigns a corresponding cell-editor with no description and a field label that reflects the field name. The properties are automatically set as modifiable (editable) and assigned a default callback function (propUpdatedCallback sub-function).
The global test_data variable is updated internally when the <OK> button is clicked. It is meant to enable easy data passing between the properties GUI and other application component. Using global vars is generally discouraged [6] as bad programming, but it simplifies GUI component interaction and has performance advantages. In this specific case I decided that the benefits of simplicity outweigh the pedagogical aspects. After all, propertiesGUI is meant to illustrate how to customize/use a properties pane, not to teach GUI programming best practices. In your real-world application you should consider using other information-sharing mechanisms (getappdata or guidata, for example).

Usage demo

For an illustration of propertiesGUI, simply run it without any parameters to display its demo (see screenshot above):

propertiesGUI;

This creates (in the demoParameters sub-function) the following demo parameters struct:

      floating_point_property: 3.14159265358979
      signed_integer_property: 12
    unsigned_integer_property: 12
                flag_property: 1
                file_property: ''
              folder_property: 'C:\Yair'
                text_property: 'Sample text'
        fixed_choice_property: {'Yes'  'No'  'Maybe'}
     editable_choice_property: {'Yes'  'No'  'Maybe'  ''}
                date_property: [1x1 java.util.Date]
        another_date_property: 734895.957829132
                time_property: '22:59:16'
            password_property: '*****'
          IP_address_property: '10.20.30.40'
                  my_category: [1x1 struct]
               color_property: [0.4 0.5 0.6]
       another_color_property: [1x1 java.awt.Color]

A template for customization

propertiesGUI is meant to be used either as stand-alone, or as a template for customization. For example, we can attach a unique description to each property that will be shown in an internal sub-panel: see the customizePropertyPane and preparePropsList sub-functions.
We can have specific control over each property’s description, label, editability, cell-editor and callback function. See the preparePropsList sub-functions for some examples. Additional cell-editors/renderers can be added in the newProperty sub-function.
Specific control over the acceptable property values can be achieved by entering custom code into the checkProp sub-function. For example, checkProp already contains skeleton code to highlight missing mandatory field values in yellow, and non-editable properties in gray (see highlighted lines; the necessary modifications to make it work should be self-evident):

function isOk = checkProp(prop)
  isOk = true;
  oldWarn = warning('off','MATLAB:hg:JavaSetHGProperty');
  warning off MATLAB:hg:PossibleDeprecatedJavaSetHGProperty
  propName = get(prop, 'UserData');
  renderer = com.jidesoft.grid.CellRendererManager.getRenderer(get(prop,'Type'), get(prop,'EditorContext'));
  warning(oldWarn);
  mandatoryFields = {};  % TODO - add the mandatory field-names here
  if any(strcmpi(propName, mandatoryFields)) && isempty(get(prop,'Value'))
      propColor = java.awt.Color.yellow;
      isOk = false;
  elseif ~prop.isEditable
      %propColor = java.awt.Color.gray;
      propColor = renderer.getBackground();
  else
      propColor = java.awt.Color.white;
  end
  renderer.setBackground(propColor);
end  % checkProp

So if we wish to check the validity of the input or user updates, we simply need to enter the relevant checks into checkProp.
Additional control over the appearance and functionality can be achieved via the hPropsPane reference that is returned by propertiesGUI.

As an example for such customizations, here is a variant of the properties pane, embedded within a uitab [7] panel. Note the unique description of the properties, and the absence of the OK/Cancel buttons:

Properties panel Integrated within a GUI
Properties panel Integrated within a GUI

TODO

Even as a template for customization, propertiesGUI is still far from perfect. Some potential items on my TODO list for this utility include:

  • Fix the renderer/editor for numeric and cell arrays
  • Enable more control over appearance and functionality via input parameters (for example: display or hide the OK/Cancel buttons)
  • Add additional built-in cell editors/renderers: time, slider, point, rectangle (=position), font, …

Do you find propertiesGUI useful in your work? If so then please share your experience in a comment below [8]. Suggestions for improvement of the utility will also be gladly accepted.

Categories: GUI, Java, Medium risk of breaking in future versions, Undocumented feature


34 Comments (Open | Close)

34 Comments To "propertiesGUI"

#1 Comment By Andrea Merlo On January 31, 2013 @ 09:59

Thanks!
Again a precious tool. I’m going to use it immediately

#2 Comment By Andrea Merlo On January 31, 2013 @ 10:47

Dear Yair,
as soon as I try to deploy a stand-alone application including propertiesGUI.m
a message box appears with “unauthorized use of JIDE products” and consequetly “please contact [15]“.
The same messagebox is displayed in the deployed application.

Am I doing something wrong? Or, which package from JIDE would you suggest.

Many thanks,
Andrea

#3 Comment By Yair Altman On January 31, 2013 @ 11:06

@Andrea – try calling com.mathworks.mwswing.MJUtilities.initJIDE before your call to propertiesGUI. I think this should be enough – let us know.

#4 Comment By Andrea Merlo On February 12, 2013 @ 11:21

Dear Yair,

I added the line you suggested, but it still provides the same message when compiling using my licensed R2008 version, the one I use to deploy applications. It appears also when compiling propertiesGUI.m alone

Message is here: [16]

No problems when compiling with R2011a.

Thanks again!
Andrea

#5 Comment By Daniel Abajo On February 23, 2016 @ 10:53

Andrea, could you find a solution for this. It happens in my application also when we have changed to 2015b

#6 Comment By Nick On May 29, 2013 @ 15:14

So it seems hgjavacomponents aren’t the original instantiation, otherwise I’d be able to (with my button) add another Property to the the Properties array in the PropertyTableModel object and see the Pane update automatically… is that right?

(This is still great though)

N

#7 Comment By Yair Altman On May 29, 2013 @ 15:19

@Nick – after you update the PropertyTableModel you need to refresh the actual data table. grid.update() should do the trick. To get the reference to grid in external code, simply modify line #1 of propertiesGUI.m to also return the grid variable.

#8 Pingback By treeTable | Undocumented Matlab On August 6, 2013 @ 04:16

[…] names and values, which is the reason it is used by Matlab’s inspect function and my generic propertiesGUI utility or Levente Hunyadi’s Property Grid utility. But in this case we wish to display a general […]

#9 Comment By Brett On August 8, 2013 @ 14:31

I saw that you used eval in order to simplify the assignment of multiple sub-fields (like ‘dimension.width’) because data.(‘dimension.width’) fails. I took a crack at a minimalist recursive struct assignment function and this is what I came up with:

function s = multiStruct(field,s)
% Function to recursively generate a struct from a string of field names
%
% field = 'life.universe.everything'
% value = 42
% answer = multiStruct(field,value)
%
% Same as answer.life.universe.everything = 42

    index=[0,strfind(field,'.')];    
    if ~isempty(field)
        s = multiStruct(field(1:index(end)-1), struct(field(index(end)+1:end),s));
    end
end

Looked at doing it with inline anonymous functions and it’s just messier than it’s worth in my opinion.

#10 Comment By Martin On August 12, 2013 @ 06:48

Or you could use the standard MATLAB function setfield, which is presumably more efficient. Assuming answer already exists and is a scalar struct and all of the nested structs are scalar, too, this would simply be

 
answer = setfield(answer, 'life', 'universe', 'everything', 42);

or if your field names are contained in a cell-array named fields

 
fields = {'life', 'universe', 'everything'};
answer = setfield(answer, fields{:}, 42);

or if you insist on using a single string with fields delimited by periods

 
fields = 'life.universe.everything';
fields = strsplit(fields, '.'); % only R2013a or higher, but more elegant
%fields = regexp(fields, '\.', 'split'); % portable, but a bit ugly
answer = setfield(answer, fields{:}, 42);

which could of course be wrapped in a separate function for convenience. The documentation of the setfield function (which can do even more) is a bit confusing on first sight, so maybe it is not instantly obvious that it can be used to create a nested struct. Equally, getfield provides easy access to values of nested structs.

#11 Comment By Yair Altman On August 12, 2013 @ 15:49

@Martin – nice touch!

#12 Comment By Ondrej On May 19, 2016 @ 21:45

I am struggling for a while with an efficient retrieving of dynamic changing substructures from a string. According to my measurements, classical for loop combined with regexp is the fastest one. However, regexp seems to be a big bottleneck in this case.

string1 = 'one.two.three.four';
A.one.two.three.four = 1;

tic
for n = 1:1000
   eval(['out1 = A.', string1, ';']);
end
toc

tic
for n = 1:1000
   out2 = eval(['A.', string1]);
end
toc

tic
for n = 1:1000
   reg1 = regexp(string1, '\.', 'split');
   out3 = getfield(A, reg1{:});
end
toc

tic
for n = 1:1000
   reg2 = regexp(string1, '\.', 'split');
   out4 = A.(reg2{1});
   for n = 2:length(reg1)
      out4 = out4.(reg2{n});
   end
end
toc

With times:
Elapsed time is 0.036253 seconds.
Elapsed time is 0.031294 seconds.
Elapsed time is 0.046321 seconds.
Elapsed time is 0.018785 seconds.

so getfield is the slowest option here and classical “sub-looping” the fastest.

Nevertheless, a faster replacement for regexp (since I am running version without strsplit) would be definitely nice.

#13 Comment By DJAMEL On October 10, 2013 @ 09:44

How to create a text dynamic under GUI/MATLAB
Thanks again

#14 Comment By Yair Altman On October 10, 2013 @ 10:05

@DJamel – you need to be much clearer in your question

#15 Comment By DJAMEL On October 12, 2013 @ 09:55

Hello

Do you have an idea how to display the results of the command
window on the GUI front in a scrolling fashion?

OR

Does a “dynamic text” box exists that allows for updates (i.e. a
returned value to be displayed to the GUI front)?
Thanks again

#16 Comment By Yair Altman On October 12, 2013 @ 13:22

I’m not sure I understand how this relates to propertiesGUI

#17 Comment By Thierry On November 19, 2013 @ 05:37

Hi Yair
do you know a way to set a file filter when using a file type with com.jidesoft.grid.FileCellEditor?
I would like for example to browse only for ‘*.exe’ files.
Same for dialog title.

#18 Comment By Thierry On November 20, 2013 @ 13:13

I could find a solution for the File filter:

editor = com.jidesoft.grid.FileCellEditor;      %('Select an .exe file','exe')
ComboBox = editor.getComboBox;
jfilefilter = javaObjectEDT('javax.swing.filechooser.FileNameExtensionFilter','Exe-Files (*.exe)','exe');
ComboBox.setFileFilter(jfilefilter);

#19 Comment By Kai On January 29, 2014 @ 09:20

I run into an error, trying the demo of the current version on R2013b:

>> propertiesGUI
No method 'setValue' with matching signature found for class
'com.jidesoft.grid.DefaultProperty'.
Error in propertiesGUI>newProperty (line 482)
      prop.setValue(thisProp);
Error in propertiesGUI>preparePropsList (line 421)
              newProp = newProperty(parameters, field_name, field_label, isEditable,
              type, field_description, @propUpdatedCallback);
Error in propertiesGUI (line 154)
  propsList = preparePropsList(parameters, isEditable); 

If I uncomment line 482, I run into this problem:

>> propertiesGUI
No constructor 'javax.swing.SpinnerNumberModel' with matching signature found.
Error in propertiesGUI>newProperty (line 503)
                            model = javax.swing.SpinnerNumberModel(prop.getValue,
                            -intmax, intmax, 1);
Error in propertiesGUI>preparePropsList (line 421)
              newProp = newProperty(parameters, field_name, field_label, isEditable,
              type, field_description, @propUpdatedCallback);
Error in propertiesGUI (line 154)
  propsList = preparePropsList(parameters, isEditable); 

any idea?

#20 Comment By Yair Altman On January 29, 2014 @ 11:33

@Kai – I assume that you are running Matlab without Java (probably some limited console mode or something like that). propertiesGUI uses Java components and so cannot possibly run in such circumstances.

#21 Comment By Kai On January 30, 2014 @ 02:14

Hi Yair,

This was not the problem.
The error was the class_object_property example: matlab.desktop.editor.getActive.
In my case it was a “1×0 Document array with properties…”.
The editor must be open for it to work.

#22 Comment By Yair Altman On January 30, 2014 @ 16:46

@Kai – are you sure that you’re using the latest propertiesGUI version (24 Dec 2013)? I believe it was already solved long ago, maybe you are using an old version…

#23 Comment By Kai On January 31, 2014 @ 05:53

Yes, that’s the version:
% $Revision: 1.09 $ $Date: 2013/12/24 14:33:21 $

And matlab:
MATLAB Version: 8.2.0.701 (R2013b)

#24 Comment By Yair Altman On January 31, 2014 @ 05:55

then this is odd because as you can see in the code, the matlab.desktop.editor.* calls are placed within try-catch blocks. Perhaps you mis-diagnosed the problem?

#25 Comment By Aleksei On April 22, 2014 @ 23:43

Dear Yair,
I can confirm that this problem holds. Tested in R2012b & R2014a. The error message arises from calling propertiesGUI with no arguments (in “demo mode”). If I supply a MATLAB structure as an argument, it seems to work fine.

#26 Comment By Jan On February 8, 2014 @ 06:45

Hi Yair,

this is a very useful submission. But wouldn’t it be better if this was written in OOP, so one could easily overload a function (e.g. a callback)?

If I got this right, I would have to make a copy of the function for every (different) purpose.

Actually, it should be not a big thing to turn it into an object, right?

Best wishes,
Jan

#27 Comment By Yair Altman On February 8, 2014 @ 10:26

@Jan – when I provide public utilities that are expected to work on old Matlab releases, before Matlab classes in their new format were introduced in R2008a, I have no option but to use standard procedural programming. This does not reflect bad programming practices or the inability to adapt to modern times, just a conscious decision to support multiple Matlab versions. I wish that other programmers were as conscious of backward compatibility as I try to be.

Feel free to adapt the code as you see fit, if you only use a new Matlab release and none of your users use an old release.

#28 Comment By Jan On February 8, 2014 @ 11:09

Ah, okay. I was not aware of that as I work on 2012b. This explains a lot!

#29 Comment By Rainer Ng On April 4, 2014 @ 06:52

Hi Yair, nice to see CHAMP being used as an example here 🙂

Problems arose after upgrading to 2014a and from talking to the tech support,

set(hProp,'UserData',propName)

is problematic. According to them, “…..The ‘UserData‘ property has been removed from the ‘DefaultProperty’ Java class in R2014a and this is an undocumented internal MATLAB component. One way to work around this would be to use a property which is defined for both versions of MATLAB like ‘Description‘. You could use the SET and GET functions to set and query values….”

#30 Comment By Yair Altman On April 4, 2014 @ 07:15

@Rainer – it’s good to hear from you again and thanks for the update!

#31 Comment By MI On September 2, 2014 @ 02:28

Hi Yair,

very good work! keep it up!

Actually I find it very useful to have a CellEditor for numeric matrix or for mixed-type table-data (cell-array).
Therefor I would like to use your app “Java-based data table” ( [17]), that is very useful for table-data!

But how can I link this Table-GUI-widget to the propertiesGUI? As I have read, we have to create a custom CellEditor that inherits from a JIDE CellEditor?
Can you give me some information how to start with that?

Or are there any built-in CellEditors that can do this?

#32 Comment By Yair Altman On September 2, 2014 @ 03:09

@MI – I will be very happy to help you integrate sophisticated table controls in your Matlab GUI, for a consulting fee. Please contact me via email (altmany at gmail).

#33 Comment By C. Chu On August 19, 2015 @ 13:50

I think I found a bug in propertiesGUI. If you have multiple field names that exist in different structs, all of those property fields are set to the same type as the last field. Here’s an example:

props = struct;
props.Info_A.Field_1 = {'A' 'B' 'C' ''};
props.Info_B.Field_2 = {'1' '2' '3' ''};
props.Info_B.Field_3 = {'X' 'Y' 'Z'};
props.Info_C.Field_1 = '';
propertiesGUI(figure, props);

The result: the first row, which should be an editable dropdown with choice ‘A’, ‘B’, or ‘C’ is now just a text box, and there’s no dropdown.

Also, some questions regarding using dates: is there a way to set a date property to empty? I’d like the box to be empty until the user fills it in the first time. Secondly, when you fill the date box you get something like “Aug 19, 2015”, but when the date selector is opened the format is dd/MM/yyyy. (I figured out how to make it yyyy-MM-dd for my own use). How do I switch the “Aug 19, 2015” view to “2015-08-19”? I’m using MATLAB R2014b.

Thanks a lot! This is an overall excellent function to use.

#34 Comment By Ahmad On December 22, 2016 @ 09:54

Hi
I want to thank from Mr Yair Altman due to its comments in GUI area. I have a question:
Is is possible to call Tow other GUI in a main GUI in the main window without opening a new window ?
My means is that i want to merge some different GUI in a main GUI with one window.
B. Regards


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

URL to article: https://undocumentedmatlab.com/articles/propertiesgui

URLs in this post:

[1] uiinspect utility: http://undocumentedmatlab.com/blog/uiinspect/

[2] PropertyTable: http://undocumentedmatlab.com/blog/jide-property-grids/

[3] downloaded: http://www.mathworks.com/matlabcentral/fileexchange/38864-propertiesgui-display-properties-in-an-editable-context-aware-table

[4] here: http://undocumentedmatlab.com/blog/tag/levente-hunyadi/

[5] “Property grid” utility: http://www.mathworks.com/matlabcentral/fileexchange/28732-property-grid-using-jide-implementation

[6] discouraged: http://en.wikipedia.org/wiki/Action_at_a_distance_%28computer_programming%29

[7] uitab: http://undocumentedmatlab.com/blog/tab-panels-uitab-and-relatives/

[8] below: http://undocumentedmatlab.com/blog/propertiesgui/#respond

[9] Color selection components : https://undocumentedmatlab.com/articles/color-selection-components

[10] uiinspect : https://undocumentedmatlab.com/articles/uiinspect

[11] Uitable sorting : https://undocumentedmatlab.com/articles/uitable-sorting

[12] JIDE Property Grids : https://undocumentedmatlab.com/articles/jide-property-grids

[13] Advanced JIDE Property Grids : https://undocumentedmatlab.com/articles/advanced-jide-property-grids

[14] Tri-state checkbox : https://undocumentedmatlab.com/articles/tri-state-checkbox

[15] : mailto:sales@jide.com

[16] : https://www.dropbox.com/s/95by7tkzbxwhgfz/JIDE%20Message.png

[17] : http://www.mathworks.com/matlabcentral/fileexchange/14225-java-based-data-table

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