I would like to welcome guest blogger Karthik Ponudurai. Today, Karthik will introduce an interesting technique for interfacing Java GUI to a Matlab application.
The current method of interfacing Java GUI controls and Matlab is by retrieving the underlying Java callback and assigning it to a Matlab callback, as shown in the following example:
% Create a Java button jButton = javacomponent(javax.swing.JButton('click me'), [20,20,60,20], gcf); % Assign a Matlab callback hButton = handle(jButton, 'CallbackProperties'); set(hButton, 'ActionPerformedCallback', @myCallback); % Matlab callback function function myCallback(hObject, hEventData) % Insert your code here end |
This approach works fine for simple pure-Java GUI created using an IDE (for example, NetBeans or Eclipse) that only have a small number of controls. You can retrieve all the Java controls in Matlab and set the callbacks as shown in the above example.
Unfortunately, practical GUIs often contain numerous controls. Assigning each control a different Matlab callback can be quite tedious.
Using a callback switchyard function
A workaround to this problem can be achieved using an invisible/hidden static Java JButton. During Matlab initialization, assign a single callback for the static Java JButton:
% Return a reference to the GUI's static trigger button triggerButton = statictrigger.triggerCls.getTrigger(); % Assign Matlab switchyard callback for triggerButton buttonProps = handle(triggerButton, 'callbackproperties'); set(triggerButton, 'ActionPerformedCallback',@TriggerCallback); |
When an event is triggered by any monitored control in the Java GUI, then within the Java code set the static button’s action command string to the desired Matlab callback name (a String) and invoke the static button’s doClick() method to trigger the Matlab TriggerCallback callback. Based on the action command string, this callback invokes the appropriate Matlab function. In this manner, Matlab’s TriggerCallback() acts as a switchyard function to the actual callback functions:
function TriggerCallback(hObject, hEventData) actionCmd = char( hObject.getActionCommand() ); hgfeval(actionCmd, hObject, hEventData); end |
Note how the char function converts the Java action command (a java.lang.String object) into Matlab char array. The requested Matlab function is then dynamically invoked using Matlab’s semi-documented hgfeval function, which Yair will describe in another article later this month.
The next few sections will look into the sample application in more detail. This application can be downloaded from here.
Java GUI
Firstly, let’s look into the Java GUI:
When the “Show Result in Matlab Dialog Box” button is clicked, the form information’s (Name, Age, Sex etc…) is saved in a hash map. This hash map is then serialized to a local file (C:\streamdata). Next, the static button’s action command string is set to ‘show’ and finally its doClick() method is invoked.
Below is the Java code corresponding to button click event:
private void showActionPerformed(java.awt.event.ActionEvent evt) { // Add form values to hash map hMap.put(name.getName(), name.getText()); hMap.put(age.getName(), age.getValue()); hMap.put(sex.getName(), (String)sex.getSelectedItem()); hMap.put(address.getName(), address.getText()); hMap.put(email.getName(), email.getText()); // Serialize hash map WriteObject(hMap); // Set trigger triggerCls.setTrigger(evt.getActionCommand()); } |
Matlab callbacks
The Java GUI sources are compiled and packaged in the statictrigger.jar file. The Matlab StaticButtonTriggerExample.m source file adds the Java library to the dynamic Java classpath:
% Add dynamic java class path javaclasspath([pwd '\javalib\statictrigger.jar']); |
The main.m function contains the code for creating the Java GUI and assigning the static button callback:
% create the statictrigger object app = statictrigger.app(); % Set static trigger button listener triggerButton = statictrigger.triggerCls.getTrigger(); buttonProps = handle(triggerButton,'callbackproperties'); set(buttonProps,'ActionPerformedCallback', {@StaticButtonTriggerCallback, app}); % Show the Java Frame app.setVisible(1); |
statictrigger.triggerCls.getTrigger() is a static Java public method that returns the static button object, for which we assign our callback switchyard function.
The following is the StaticButtonTriggerCallback.m code, which displays the information in a Matlab message-box:
% Get action command string actionCommand = src.getActionCommand(); % Read in serialized hash map hashMap = app.ReadObject(); % Convert hash map to Matlab structure data = Hash2Struct(hashMap); % Display data in Matlab dialog box msg = ['Name: ' char(hashMap.get('name')) ... ', Age: ' num2str(hashMap.get('age')) ... ', Sex: ' char(hashMap.get('sex')) ... ', Address: ' char(hashMap.get('address')) ... ', Email: ' char(hashMap.get('email')) ]; uiwait(helpdlg(msg, 'Form Details')); |
You can download the example’s files from here. Extract the zip file, cd to the newly-generated StaticButtonTrigger folder, then invoke the StaticButtonTriggerExample.m function to run the example.
I have tried similar technique
http://mathforum.org/kb/thread.jspa?forumID=80&threadID=1639114&messageID=5950848
in a more general scenario, not directly bound to UI events to replace this older JMI-based approach
http://www.cs.virginia.edu/~whitehouse/matlab/JavaMatlab.html
But somehow it has not worked for me …
Welcome aboard Mikhail 🙂
Haven’t seen you around CSSM in a very long time – you’ve been missed…
Funny that the MathForum link you posted doesn’t appear on CSSM – I was under the impression that MathForum was a simple CSSM mirror
-Yair
Hi Mikhail,
I have also tried the JMI solution from
http://www.cs.virginia.edu/~whitehouse/matlab/JavaMatlab.html
and I realise quickly how complicated it is to get it working, and running MATLAB as a server is not a good option for us.
We code and deploy MATLAB application to users, and the above solution enable us to develop a nice looking front end with a simple communication protocol.
Thanks.
Karthik
@Karthik: you misunderstood me. See my first link – the solution I tried three years ago very is similar to yours! Bur I encountered problems with it and had to stay with JMI which works fine. I will try your solution on this weekend!
Hi Mikhail, got you now. Let me know how it goes. Good luck!
Very nice example !
Is it possible to have also the java source code, to see all interactions between java and matlab ?
Thanks
Eric
Hi Eric,
Thanks for the comment. The Java source code is now included in the downloadable ZIP file.
Karthik
Hi Karthik,
Sorry to disturb you again, but the zip file only include the .jar file.
In fact I would like to see the .java file if it’s possible.
I’m new in developping Java GUI inside Matlab, and I would like to use it as a base for my GUIs. I read on the web that it’s important to focus on EDT management between Matlab and Java, but it isn’t well documented. And it seems that your example can be a good base for any GUI development, isn’t it ?
Eric
@Eric – the Java source files are included in the ZIP file, in the StaticButtonTrigger\javalib\ folder
– Yair
Hi Eric,
To build a pratical Java GUI in MATLAB you still need to keep the main Window as MATLAB figure and use Yair’s UISpiltPane (http://www.mathworks.com/matlabcentral/fileexchange/23073) to divide MATLAB figure into sub panels. The reason for using MATLAB figure is because currently you still need a MATLAB’s uipanel to add a plotting axes (http://www.mathworks.de/matlabcentral/newsreader/view_thread/148719).
You can then use JControl (http://www.mathworks.com/matlabcentral/fileexchange/15580-using-java-swing-components-in-matlab) to integrate Java components (example java JPanel, JDesktopPane, etc…) to the sub panels.
It’s also worth looking at Infonode (http://www.infonode.net/) Java GUI inplementation which allows docking windows. I have implemented Infonode in MATLAB and it does extend the MATLAB’s GUI capability.
Karthik
Hi Karthik
I am working in a project similar to what you have said above . We are using NetBeans to create our own web application and we need to interface Matlab with JSP and servlets. Since servlets is the Java code, will we be able to interface it with Matlab in the way you have said above?
Regards
Suganya
Hi Suganya,
I personally have not worked with Servlets or web application. I don’t think MATLAB includes the java libraries for servlets in the static library path, but you could add the libraries to the dynamic path during runtime and then access all the classes within MATLAB.
Sorry for the late reply as I did not receive a notification email. If you have any further question, email me at karthik.ponudurai@gmail.com
Karthik
Hi,
I want to enquire about the events generated upon opening or closing a dialog box(e.g-Function Block Parameters or Source Block Parameters). Is there any way I can get these events and register their listeners.
Thanks & Regards
Anubhav Jain
@Anubhav – you need to get the dialog handle before you can register any listener on it…
Hi,
Thanks a lot for your immediate response.
Actually I wanted to get the name of an event associated with closing of function parameter dialog box for example if I change threshold value of a switch block and apply it then I should be able to listen to the event of closing of that parameter box. Can you please help me out with this.
Thanks & Regards
Anubhav Jain.
@Anubhav – you can perhaps trap the dialog figure’s DeleteFcn callback.
@Anubhav – This is a complicated area and you will have to do a lot of reasearch on your own to accomplish what you are looking for. The first thing to know is that the Simulink editor is not java based so none of the java techniques are going to be of use to you. Simulink to a certian extent is UDD based. There are two primary UDD packages you will need to study using the techniques from the series of articles on UDD. The first package is the ‘DAStudio’ package. The second is the ‘Simulink’ Package. DAStudio to a certian extent is the base package as it contains an object called DAStudio.Object which is the Superclass for Simulink.Object which in turn is the Superclass for most of the rest of the Simulink classes in the Simulink package. To a certian extent the uses for these packages can be divided as follows. Models are built from classes in the Simulink Package while Dialogs come from the DAStudio package. The parameter dialogs you are looking at are of tyoe DAStudio.Dialog. They do not generate any events on their own. They are however hierarchical children of DAStudio.ToolRoot. So in theory you can monitor an instance of DAStudio.ToolRoot for the events ‘ObjectsChildAdded’ and ‘ObjectChildRemoved’ using the methods in the Hiearchical Systems with UDD and UDD events posts.
Good Luck,
Donn
I think there’s a typo in the original code – in the 2nd code block, the first one after the heading “Using a callback switchyard function”. It says
but I’m pretty sure that should be
At least, the first one doesn’t work for me, and the second one does. (I’m using Matlab 2012a, but I don’t think that’s the issue.)
Thanks for lots of great Matlab help!
/rob
@Rob – thanks for the correction. I fixed the article accordingly.
Well done.
I would add that as you are passing the Matlab instantiated app object around couldn’t you change the hMap to public and access it without the file I/O?
Although getters/setters are probably a more acceptable route.
Hello,
I am trying to open a UI created in Java SWT through Matlab.
But I am getting following error..
Can any one help me in this…
thanking you in advance.
—
Nikhil
@Nikhil – try adding
C:\Users\x_shirod\.swt\lib\win32\x86_64\
to your librarypath.txt file:Hi,
I am trying to launch matlab model and control its execution through Java Interface. Please let me know if their are any ways to do this.
Any response will help.
Thanks,
jai Naresh
@Jai – take a look at JMI: http://undocumentedmatlab.com/blog/jmi-java-to-matlab-interface/
So, I am trying the following:
I added a listener to a Simulink block.
When trying to execute a public function of my JAR file within the listener, I get an error.
I tried to use a timer to see if that would solve the issue. However, it didn’t work.
Any clues?
Why you getting a handle if you don´t use it?
@Tom – you are correct. This was simply a typo (
jButton
instead ofhButton
). I corrected the main text accordingly.