I would like to welcome repeat guest blogger Karthik Ponudurai, who has previously written here about the JTattoo look-and-feel, and about integration of Java controls’ events with Matlab callbacks. Today, Karthik discusses a problem when we wish to use pure-Java GUIs in deployed Matlab programs, and the undocumented simple solution.
Reminder: I will be visiting several US cities (Minneapolis, Boston and New York) in July 22-31 (details). Let me know if you’d like to meet me there.
Using a pure-Java Swing-based Graphical User Interface (GUI) has several important advantages compared to using a pure-Matlab GUI:
- Java GUI widget toolkit provides a large collection of components (scrollbar, slider, etc…) and layouts (card, spring, etc…)
- Multiple event handling options
- Mature third-party Java Swing IDEs for quick and easy GUI development (Netbeans, Eclipse, etc…)
- Supports pluggable look and feel that allows applications to have a look and feel that is unrelated to the underlying platform.
- Java Swing’s window icon can be modified, whereas Mathworks apparently places an [entirely unreasonable] license restriction on modifying the Matlab figure window icon.
When Matlab is in development (non-deployed) mode, we can load and display a Java
JFrame using the following Matlab code:
% Add Java library to dynamic Java classpath javaaddpath([pwd '\ExampleWindow.jar']); % Get example Java window from the library jFrame = examplewindow.JavaWindow(); % Get Java buttons % Note: see https://undocumentedmatlab.com/blog/matlab-callbacks-for-java-events-in-r2014a plotMeshButton = handle(jFrame.getPlotMeshButton(), 'CallbackProperties'); showWarnButton = handle(jFrame.getShowWarnDlgButton(), 'CallbackProperties'); % Set Java button callbacks set(plotMeshButton, 'ActionPerformedCallback', @myPlotMeshCallback); set(showWarnButton, 'ActionPerformedCallback', @myShowWarnCallback); % Display the Java window jFrame.setVisible(true);
Java JFrame created in Matlab (click for full-size image)
All this works great when ran within the Matlab environment. However, when the Matlab source code file (.m) is compiled as a Windows standalone executable application, when running the resulting executable the Java window appears for a short period and then terminates (exits). Without a visible Matlab figure, the compiled Matlab application does not retain the Java window open. The JFrame flashes on for a split-second, and then vanishes.
To fix this problem, it turns out that we only need to add the Matlab waitfor command after making the Java window visible:
% (earlier code as above) % Display the Java window jFrame.setVisible(true); if isdeployed waitfor(jFrame); end
Java JFrame in deployed Matlab (click for full-size image)
The waitfor command holds the Java window open, but still enables full interactivity with the window: When a control event is triggered, the specified callback is executed, and then Matlab returns to the waitfor.
A zip file containing the Matlab source-code and its resulting executable can be downloaded from here. You might get a security notification when downloading the zip file, due to the contained exe file. Also note that to run the executable, you need to install Matlab MCR R2012b (8.0) or later, otherwise you will get a run-time error.
Finally, note that closing the Java GUI exits the JVM and by extension the entire containing program (Matlab). Naturally, this has no impact in deployed mode, but to prevent it from exiting the Matlab environment in non-deployed mode, don’t close the Java window by clicking its “X” button etc., but rather by calling
jFrame.dispose(); in your Matlab code or the Matlab Desktop’s Command Window.