Java – Undocumented Matlab https://undocumentedmatlab.com Charting Matlab's unsupported hidden underbelly Wed, 17 Jan 2018 20:42:44 +0000 en-US hourly 1 https://wordpress.org/?v=4.4.1 Toolbar button labelshttps://undocumentedmatlab.com/blog/toolbar-button-labels https://undocumentedmatlab.com/blog/toolbar-button-labels#respond Mon, 08 Jan 2018 17:34:17 +0000 https://undocumentedmatlab.com/?p=7270

Related posts:
1. Customizing figure toolbar background Setting the figure toolbar's background color can easily be done using just a tiny bit of Java magic powder. This article explains how. ...
2. Builtin PopupPanel widget We can use a built-in Matlab popup-panel widget control to display lightweight popups that are attached to a figure window. ...
3. FindJObj – find a Matlab component’s underlying Java object The FindJObj utility can be used to access and display the internal components of Matlab controls and containers. This article explains its uses and inner mechanism....
4. FindJObj GUI – display container hierarchy The FindJObj utility can be used to present a GUI that displays a Matlab container's internal Java components, properties and callbacks....

]]>
I was recently asked by a client to add a few buttons labeled “1”-“4” to a GUI toolbar. I thought: How hard could that be? Simply get the toolbar’s handle from the figure, then use the builtin uipushtool function to add a new button, specifying the label in the String property, right?

Well, not so fast it seems:

hToolbar = findall(hFig, 'tag','FigureToolBar'); % get the figure's toolbar handle uipushtool(hToolbar, 'String','1'); % add a pushbutton to the toolbar Error using uipushtool There is no String property on the PushTool class. 

Apparently, for some unknown reason, standard Matlab only enables us to set the icon (CData) of a toolbar control, but not a text label.

Once again, Java to the rescue:

We first get the Java toolbar reference handle, then add the button in standard Matlab (using uipushtool, uitoggletool and their kin). We can now access the Java toolbar’s last component, relying on the fact that Matlab always adds new buttons at the end of the toolbar. Note that we need to use a short drawnow to ensure that the toolbar is fully re-rendered, otherwise we’d get an invalid Java handle. Finally, once we have this reference handle to the underlying Java button component, we can set and customize its label text and appearance (font face, border, size, alignment etc.):

hToolbar = findall(hFig, 'tag','FigureToolBar'); % get the figure's toolbar handle jToolbar = hToolbar.JavaContainer.getComponentPeer; % get the toolbar's Java handle for buttonIdx = 1 : 4 % First create the toolbar button using standard Matlab code label = num2str(buttonIdx); % create a string label uipushtool(hToolbar, 'ClickedCallback',{@myCallback,analysisIdx}, 'TooltipString',['Run analysis #' label]);   % Get the Java reference handle to the newly-created button drawnow; pause(0.01); % allow the GUI time to re-render the toolbar jButton = jToolbar.getComponent(jToolbar.getComponentCount-1);   % Set the button's label jButton.setText(label) end

The standard Matlab toolbar button size (23×23 pixels) is too small to display more than a few characters. To display a longer label, we need to widen the button:

% Make the button wider than the standard 23 pixels newSize = java.awt.Dimension(50, jButton.getHeight); jButton.setMaximumSize(newSize) jButton.setPreferredSize(newSize) jButton.setSize(newSize)

Using a text label does not prevent us from also displaying an icon: In addition to the text label, we can also display a standard icon (by setting the button’s CData property in standard Matlab). This icon will be displayed to the left of the text label. You can widen the button, as shown in the code snippet above, to make space for both the icon and the label. If you want to move the label to a different location relative to the icon, simply modify the Java component’s HorizontalTextPosition property:

jButton.setHorizontalTextPosition(jButton.RIGHT); % label right of icon (=default) jButton.setHorizontalTextPosition(jButton.CENTER); % label on top of icon jButton.setHorizontalTextPosition(jButton.LEFT); % label left of icon

In summary, here’s the code snippet that generated the screenshot above:

% Get the Matlab & Java handles to the figure's toolbar hToolbar = findall(hFig, 'tag','FigureToolBar'); % get the figure's toolbar handle jToolbar = hToolbar.JavaContainer.getComponentPeer; % get the toolbar's Java handle   % Button #1: label only, no icon, 23x23 pixels h1 = uipushtool(hToolbar); drawnow; pause(0.01); jButton = jToolbar.getComponent(jToolbar.getComponentCount-1); jButton.setText('1')   % Create the icon CData from an icon file graphIcon = fullfile(matlabroot,'/toolbox/matlab/icons/plotpicker-plot.gif'); [graphImg,map] = imread(graphIcon); map(map(:,1)+map(:,2)+map(:,3)==3) = NaN; % Convert white pixels => transparent background cdata = ind2rgb(graphImg,map);   % Button #2: label centered on top of icon, 23x23 pixels h2 = uipushtool(hToolbar, 'CData',cdata); drawnow; pause(0.01); jButton = jToolbar.getComponent(jToolbar.getComponentCount-1); jButton.setText('2') jButton.setHorizontalTextPosition(jButton.CENTER)   % Button #3: label on right of icon, 50x23 pixels h3 = uipushtool(hToolbar, 'CData',cdata); drawnow; pause(0.01); jButton = jToolbar.getComponent(jToolbar.getComponentCount-1); jButton.setText('3...') d = java.awt.Dimension(50, jButton.getHeight); jButton.setMaximumSize(d); jButton.setPreferredSize(d); jButton.setSize(d)   % Button #4: label on left of icon, 70x23 pixels h4 = uipushtool(hToolbar, 'CData',cdata); drawnow; pause(0.01); jButton = jToolbar.getComponent(jToolbar.getComponentCount-1); jButton.setText('and 4:') jButton.setHorizontalTextPosition(jButton.LEFT) d = java.awt.Dimension(70, jButton.getHeight); jButton.setMaximumSize(d); jButton.setPreferredSize(d); jButton.setSize(d)

Many additional toolbar customizations can be found here and in my book “Undocumented Secrets of MATLAB-Java Programming“. If you’d like me to design a professional-looking GUI for you, please contact me.

Caveat emptor: all this only works with the regular Java-based GUI figures, not web-based (“App-Designer”) uifigures.

]]>
https://undocumentedmatlab.com/blog/toolbar-button-labels/feed 0
Using SQLite in Matlabhttps://undocumentedmatlab.com/blog/using-sqlite-in-matlab https://undocumentedmatlab.com/blog/using-sqlite-in-matlab#respond Wed, 27 Dec 2017 21:53:54 +0000 https://undocumentedmatlab.com/?p=7255

Related posts:
1. Speeding up Matlab-JDBC SQL queries Fetching SQL ResultSet data from JDBC into Matlab can be made significantly faster. ...
2. Types of undocumented Matlab aspects This article lists the different types of undocumented/unsupported/hidden aspects in Matlab...
3. ScreenCapture utility The ScreenCapture utility uses purely-documented Matlab for capturing a screen region as an image from within Matlab. ...
4. Smart listbox & editbox scrollbars Matlab listbox and multi-line editbox scrollbars can easily be made smarter, for improved appearance. ...

]]>
MathWorks invests a huge amount of effort in recent years on supporting large distributed databases. The business case for this focus is entirely understandable, but many Matlab users have much simpler needs, which are often served by the light-weight open-source SQLite database (which claims to be the most widely-used database worldwide). Although SQLite is very widely used, and despite the fact that built-in support for SQLite is included in Matlab (for its internal use), MathWorks has chosen not to expose any functionality or wrapper function that would enable end-users to access it. In any case, I recently came across a need to do just that, when a consulting client asked me to create an interactive data-browser for their SQLite database that would integrate with their Matlab program:

In today’s post I will discuss several possible mechanisms to integrate SQLite in Matlab code, and you can take your pick among them. Except for the Database Toolbox, all the alternatives are free (open-source) libraries (even the commercial Database Toolbox relies on one of the open-source libraries, by the way).

### sqlite4java

sqlite4java is a Java package by ALM Works that is bundled with Matlab for the past several years (in the %matlabroot%/java/jarext/sqlite4java/ folder). This is a lightweight open-source package that provides a minimalist and fast (although not very convenient) interface to SQLite. You can either use the package that comes with your Matlab installation, or download and use the latest version from the project repository, where you can also find documentation.

Mark Mikofski exposed this hidden nugget back in 2015, and you are welcome to view his post for additional details. Here’s a sample usage:

% Open the DB data file db = com.almworks.sqlite4java.SQLiteConnection(java.io.File('C:\Yair\Data\IGdb 2017-11-13.sqlite')); db.open;   % Prepare an SQL query statement stmt = db.prepare(['select * from data_table where ' conditionStr]);   % Step through the result set rows row = 1; while stmt.step numericValues(row) = stmt.columnInt(0); % column #0 stringValues{row} = stmt.columnString(1); % column #1 end   % Cleanup stmt.dispose db.dispose

Note that since sqlite4java uses a proprietary interface (similar, but not identical, to JDBC), it can take a bit of time to get used to it. I am generally a big fan of preferring built-in components over externally-installed ones, but in this particular case I prefer other alternatives.

### JDBC

JDBC (Java Database Connectivity) is the industry standard for connectivity to databases. Practically all databases nowadays have at least one JDBC connector, and many DBs have multiple JDBC drivers created by different groups. As long as they all adhere to the JDBC interface standard, these drivers are all equivalent and you can choose between them based on availability, cost, support, license, performance and other similar factors. SQLite is no exception to this rule, and has several JDBC driver implementations, including xerial’s sqlite-jdbc (also discussed by Mark Mikofski) and sqlitejdbc. If you ask me,
sqlite-jdbc is better as it is being maintained with new versions released periodically.

The example above would look something like this with sqlite-jdbc:

% Add the downloaded JAR library file to the dynamic Java classpath javaaddpath('C:\path\to\sqlite\sqlite-jdbc-3.21.0.jar')   % Open the DB file jdbc = org.sqlite.JDBC; props = java.util.Properties; conn = jdbc.createConnection('jdbc:sqlite:C:\Yair\Data\IGdb 2017-11-13.sqlite',props); % org.sqlite.SQLiteConnection object   % Prepare and run an SQL query statement sqlStr = ['select * from data_table where ' conditionStr]; stmt = conn.createStatement; % org.sqlite.jdbc4.JDBC4Statement object rs = stmt.executeQuery(sqlStr); % org.sqlite.jdbc4.JDBC4ResultSet object   % Step through the result set rows rows = 1; while rs.next numericValues(row) = rs.getLong('ID'); stringValues{row} = rs.getString('Name'); end   % Cleanup rs.close stmt.close conn.close

### Database toolbox

In addition to all the above, MathWorks sells the Database Toolbox which has an integral SQLite connector, in two flavors – native and JDBC (the JDBC connector is simply sqlite-jdbc that I mentioned above, see a short discussion here).

I assume that the availability of this feature in the DB toolbox is the reason why MathWorks has never created a documented wrapper function for the bundled sqlite4java. I could certainly understand this from a business perspective. Still, with so many free alternatives available as discussed in this post, I see not reason to purchase the toolbox merely for its SQLite connector. Then again, if you need to connect to several different database types, not just SQLite, then getting the toolbox might make sense.

### mksqlite

My personal favorite is actually none of these Java-based connectors (surprise, surprise), but rather the open-source mksqlite connector by Martin Kortmann and Andreas Martin. This is a native (Mex-file) connector that acts as a direct Matlab function. The syntax is pretty straight-forward and supports SQL queries. IMHO, its usage is a much simpler than with any of the other alternatives:

% Open the DB file mksqlite('open', 'C:\Yair\Data\IGdb 2017-11-13.sqlite');   % Query the database results = mksqlite(['select * from data_table where ' conditionStr]); numericValues = [results.ID]; stringValues = {results.Name};   % Cleanup mksqlite('close');

Can it be any simpler than this!?

However, the main benefit of mksqlite over the other connectors is not its simplicity but the connector’s speed. This speed is due to the fact that the query is vectorized and we do not need to loop over all the separate data rows and fields. With the other connectors, it is actually not the loop that takes so long in Matlab, but rather the overheads and inefficiencies of numerous library calls to fetch one single value at a time from the result-set – this is avoided in mksqlite where there is only a single call. This results in lightning speed: A couple of years ago I consulted to a client who used a JDBC connector to an SQLite database; by switching from a JDBC connector to mksqlite, I reduced the execution time from 7 secs to 70 msecs – a 100x speedup! In that specific case, this made the difference between an unusable program and a highly interactive/responsive one.

### Other alternatives

In addition to all the above, we can also use a .NET-based connector or a Python one – I leave these as an exercise for the reader…

Have I forgotten some important alternative? Or perhaps you have have some related tip you’d like to share? If so, then please leave a comment below.

Happy New Year everybody!

]]>
https://undocumentedmatlab.com/blog/using-sqlite-in-matlab/feed 0
PlotEdit context-menu customizationhttps://undocumentedmatlab.com/blog/plotedit-context-menu-customization https://undocumentedmatlab.com/blog/plotedit-context-menu-customization#respond Wed, 13 Dec 2017 12:57:14 +0000 https://undocumentedmatlab.com/?p=7236

Related posts:
1. FindJObj – find a Matlab component’s underlying Java object The FindJObj utility can be used to access and display the internal components of Matlab controls and containers. This article explains its uses and inner mechanism....
2. FindJObj GUI – display container hierarchy The FindJObj utility can be used to present a GUI that displays a Matlab container's internal Java components, properties and callbacks....
3. Tab panels – uitab and relatives This article describes several undocumented Matlab functions that support tab-panels...
4. Customizing figure toolbar background Setting the figure toolbar's background color can easily be done using just a tiny bit of Java magic powder. This article explains how. ...

]]>
Last week, a Matlab user asked whether it is possible to customize the context (right-click) menu that is presented in plot-edit mode. This menu is displayed by clicking the plot-edit (arrow) icon on the standard Matlab figure toolbar, then right-clicking any graphic/GUI element in the figure. Unfortunately, it seems that this context menu is only created the first time that a user right-clicks in plot-edit mode – it is not accessible before then, and so it seems impossible to customize the menu before it is presented to the user the first time.

A few workarounds were suggested to the original poster and you are most welcome to review them. There is also some discussion about the technical reasons that none of the “standard” ways of finding and modifying menu items fail in this case.

In today’s post I wish to repost my solution, in the hope that it might help other users in similar cases.

My solution is basically this:

1. First, enter plot-edit mode programmatically using the plotedit function
2. Next, move the mouse to the screen location of the relevant figure component (e.g. axes). This can be done in several different ways (the root object’s PointerLocation property, the moveptr function, or java.awt.Robot.mouseMove() method).
3. Next, automate a mouse right-click using the built in java.awt.Robot class (as discussed in this blog back in 2010)
4. Next, locate the relevant context-menu item and modify its label, callback or any of its other properties
5. Next, dismiss the context-menu by simulating a follow-on right-click using the same Robot object
6. Finally, exit plot-edit mode and return the mouse pointer to its original location
% Create an initial figure / axes for demostration purpose fig = figure('MenuBar','none','Toolbar','figure'); plot(1:5); drawnow;   % Enter plot-edit mode temporarily plotedit(fig,'on'); drawnow   % Preserve the current mouse pointer location oldPos = get(0,'PointerLocation');   % Move the mouse pointer to within the axes boundary % ref: https://undocumentedmatlab.com/blog/undocumented-mouse-pointer-functions figPos = getpixelposition(fig); % figure position axPos = getpixelposition(gca,1); % axes position figure(fig); % ensure that the figure is in focus newPos = figPos(1:2) + axPos(1:2) + axPos(3:4)/4; % new pointer position set(0,'PointerLocation',newPos); % alternatives: moveptr(), java.awt.Robot.mouseMove()   % Simulate a right-click using Java robot % ref: https://undocumentedmatlab.com/blog/gui-automation-robot robot = java.awt.Robot; robot.mousePress (java.awt.event.InputEvent.BUTTON3_MASK); pause(0.1) robot.mouseRelease(java.awt.event.InputEvent.BUTTON3_MASK); pause(0.1)   % Modify the <clear-axes> menu item hMenuItem = findall(fig,'Label','Clear Axes'); if ~isempty(hMenuItem) label = '<html><b><i><font color="blue">Undocumented Matlab'; callback = 'web(''https://undocumentedmatlab.com'',''-browser'');'; set(hMenuItem, 'Label',label, 'Callback',callback); end   % Hide the context menu by simulating a left-click slightly offset set(0,'PointerLocation',newPos+[-2,2]); % 2 pixels up-and-left pause(0.1) robot.mousePress (java.awt.event.InputEvent.BUTTON1_MASK); pause(0.1) robot.mouseRelease(java.awt.event.InputEvent.BUTTON1_MASK); pause(0.1)   % Exit plot-edit mode plotedit(fig,'off'); drawnow   % Restore the mouse pointer to its previous location set(0,'PointerLocation',oldPos);

In this code, I sprinkled a few pauses at several locations, to ensure that everything has time to fully render. Different pause values, or perhaps no pause at all, may be needed on your specific system.

Modifying the default context-menu shown in plot-edit mode may perhaps be an uncommon use-case. But the technique that I demonstrated above – of using a combination of Matlab and Java Robot commands to automate a certain animation – can well be used in many other use-cases where we cannot easily access the underlying code. For example, when the internal code is encoded/encrypted, or when a certain functionality (such as the plot-edit context-menu) is created on-the-fly.

If you have encountered a similar use-case where such automated animations can be used effectively, please add a comment below.

]]>
Builtin PopupPanel widgethttps://undocumentedmatlab.com/blog/builtin-popuppanel-widget https://undocumentedmatlab.com/blog/builtin-popuppanel-widget#respond Wed, 06 Dec 2017 16:00:34 +0000 https://undocumentedmatlab.com/?p=7188

Related posts:
1. Toolbar button labels GUI toolbar button labels can easily be set and customized using underlying Java components. ...
2. Uitable sorting Matlab's uitables can be sortable using simple undocumented features...
3. Customizing figure toolbar background Setting the figure toolbar's background color can easily be done using just a tiny bit of Java magic powder. This article explains how. ...
4. Frameless (undecorated) figure windows Matlab figure windows can be made undecorated (borderless, title-less). ...

]]>
8 years ago I blogged about Matlab’s builtin HelpPopup widget. This control is used by Matlab to display popup-windows with help documentation, but can also be used by users to display custom lightweight popups that contain HTML-capable text and even URLs of entire webpages. Today I’d like to highlight another builtin Matlab widget, ctrluis.PopupPanel, which can be used to display rich contents in a lightweight popup box attached to a specific Matlab figure:

Matlab's builtin PopupPanel widget

As you can see, this popup-panel displays richly-formatted contents, having either an opaque or transparent background, with vertical scrollbars being applied automatically. The popup pane is not limited to displaying text messages – in fact, it can display any Java GUI container (e.g. a settings panel). This popup-panel is similar in concept to the HelpPopup widget, and yet much more powerful in several aspects.

### Creating the popup panel

Creating a PopupPanel is very simple:

% Create the popup-panel in the specified figure hPopupPanel = ctrluis.PopupPanel(gcf); % use gcf or any figure handle hPopupPanel.setPosition([.1,.1,.8,.8]); % set panel position (normalized units)   % Alternative #1: set popup-panel's contents to some HTML-formatted message % note: createMessageTextPane() has optional input args FontName (arg #2), FontSize (#3) jPanel = ctrluis.PopupPanel.createMessageTextPane('testing <b><i>123</i></b> ...') hPopupPanel.setPanel(jPanel);   % Alternative #2: set popup-panel's contents to a webpage URL url = 'http://undocumentedmatlab.com/files/sample-webpage.html'; jPanel = javaObjectEDT(javax.swing.JEditorPane(url)); hPopupPanel.setPanel(jPanel);

The entire contents are embedded within a scroll-box (which is a com.mathworks.widgets.LightScrollPane object) whose scrollbars automatically appear as-needed, so we don’t need to worry about the contents fitting the allocated space.

To display custom GUI controls in the popup, we can simply contain those GUI controls in a Java container (e.g., a JPanel) and then do hPopupPanel.setPanel(jPanel). This functionality can be used to create unobtrusive settings panels, input dialogs etc.

The nice thing about the popup widget is that it is attached to the figure, and yet is not assigned a heavyweight window (so it does not appear in the OS task-bar). The popup moves along with the figure when the figure is moved, and is automatically disposed when the figure is closed.

A few caveats about the ctrluis.PopupPanel control:

• The widget’s parent is expected to be a figure that has pixel units. If it doesn’t, the internal computations of ctrluis.PopupPanel croak.
• The widget’s position is specified in normalized units (default: [0,0,1,1]). This normalized position is only used during widget creation: after creation, if you resize the figure the popup-panel’s position remains unchanged. To modify/update the position of the popup-panel programmatically, use hPopupPanel.setPosition(newPosition). Alternatively, update the control’s Position property and then call hPopupPanel.layout() (there is no need to call layout when you use setPosition).
• This functionality is only available for Java-based figures, not the new web-based (AppDesigner) uifigures.

### Popup panel customizations

We can open/close the popup panel by clicking on its icon, as shown in the screenshots above, or programmatically using the control’s methods:

% Programmatically open/close the popup-panel hPopupPanel.showPanel; hPopupPanel.hidePanel;   % Show/hide entire popup-panel widget (including its icon) hPopupPanel.setVisible(true); % or .setVisible(1) or .Visible=1 hPopupPanel.setVisible(false); % or .setVisible(0) or .Visible=0

To set a transparent background to the popup-panel (as shown in the screenshots above), we need to unset the opacity of the displayed panel and several of its direct parents:

% Set a transparent popup-panel background for idx = 1 : 6 jPanel.setOpaque(false); % true=opaque, false=transparent jPanel = jPanel.getParent; end jPanel.repaint

Note that in the screenshots above, the panel’s background is made transparent, but the contained text and image remain opaque. Your displayed images can of course contain transparency and animation, if this is supported by the image format (for example, GIF).

ctrluis.PopupPanel is used internally by iptui.internal.utilities.addMessagePane(hFig,message) in order to display a minimizable single-line message panel at the top of a specified figure:

hPopupPanel = iptui.internal.utilities.addMessagePane(gcf, 'testing <b>123</b> ...'); % note the HTML formatting

The function updates the message panel’s position whenever the figure’s size is modified (by trapping the figure’s SizeChangedFcn), to ensure that the panel is always attached to the top of the figure and spans the full figure width. This is a simple function so I encourage you to take a look at its code (%matlabroot%/toolbox/images/imuitools/+iptui/+internal/+utilities/addMessagePane.m) – note that this might require the Image Processing Toolbox (I’m not sure).

### Professional assistance anyone?

As shown by this and many other posts on this site, a polished interface and functionality is often composed of small professional touches, many of which are not exposed in the official Matlab documentation for various reasons. So if you need top-quality professional appearance/functionality in your Matlab program, or maybe just a Matlab program that is dependable, robust and highly-performant, consider employing my consulting services.

]]>
https://undocumentedmatlab.com/blog/builtin-popuppanel-widget/feed 0
Sending HTML emails from Matlabhttps://undocumentedmatlab.com/blog/sending-html-emails-from-matlab https://undocumentedmatlab.com/blog/sending-html-emails-from-matlab#comments Wed, 02 Aug 2017 21:19:42 +0000 http://undocumentedmatlab.com/?p=6986

Related posts:
1. Uitable sorting Matlab's uitables can be sortable using simple undocumented features...
2. Uitable customization report Matlab's uitable can be customized in many different ways. A detailed report explains how. ...
3. Types of undocumented Matlab aspects This article lists the different types of undocumented/unsupported/hidden aspects in Matlab...
4. Multi-line uitable column headers Matlab uitables can present long column headers in multiple lines, for improved readability. ...

]]>
A few months ago I wrote about various tricks for sending email/text messages from Matlab. Unfortunately, Matlab only sends text emails by default and provides no documented way to send HTML-formatted emails. Text-only emails are naturally very bland and all mail clients in the past 2 decades support HTML-formatted emails. Today I will show how we can send such HTML emails from Matlab.

A quick recap: Matlab’s sendmail function uses Java (specifically, the standard javax.mail package) to prepare and send emails. The Java classes are extremely powerful and so there is no wonder that Mathworks chose to use them rather than reinventing the wheel. However, Matlab’s sendmail function only uses part of the functionality exposed by these classes (admittedly, the most important parts that deal with the basic mail-sending mechanism), and does not expose external hooks or input args that would enable the user to take full advantage of the more advanced features, HTML formatting included.

Only two small changes are needed in sendmail.m to support HTML formatting:

1. HTML formatting required calling the message-object’s setContent() method, rather than setText().
2. We need to specify 'text/html' as part of the message’s encoding

To implement these features, change the following (lines #119-130 in the original sendmail.m file of R2017a, changed lines highlighted):

% Construct the body of the message and attachments. body = formatText(theMessage); if numel(attachments) == 0 if ~isempty(charset) msg.setText(body, charset); else msg.setText(body); end else % Add body text. messageBodyPart = MimeBodyPart; if ~isempty(charset) messageBodyPart.setText(body, charset); ...

to this (changed lines highlighted):

% Construct the body of the message and attachments. body = formatText(theMessage); isHtml = ~isempty(body) && body(1) == '<'; % msg starting with '<' indicates HTMLif isHtml if isempty(charset) charset = 'text/html; charset=utf-8'; else charset = ['text/html; charset=' charset]; endendif numel(attachments) == 0 && ~isHtml if isHtml msg.setContent(body, charset); elseif ~isempty(charset) msg.setText(body, charset); else msg.setText(body); end else % Add body text. messageBodyPart = MimeBodyPart; if isHtml messageBodyPart.setContent(body, charset); elseif ~isempty(charset) messageBodyPart.setText(body, charset); ...

In addition, I also found it useful to remove the hard-coded 75-character line-wrapping in text messages. This can be done by changing the following (line #291 in the original sendmail.m file of R2017a):

maxLineLength = 75;

to this:

maxLineLength = inf; % or some other large numeric value

### Deployment

It’s useful to note two alternatives for making these fixes:

• Making the changes directly in %matlabroot%/toolbox/matlab/iofun/sendmail.m. You will need administrator rights to edit this file. You will also need to redo the fix whenever you install Matlab, either installation on a different machine, or installing a new Matlab release. In general, I discourage changing Matlab’s internal files because it is simply not very maintainable.
• Copying %matlabroot%/toolbox/matlab/iofun/sendmail.m into a dedicated wrapper function (e.g., sendEmail.m) that has a similar function signature and exists on the Matlab path. This has the benefit of working on multiple Matlab releases, and being copied along with the rest of our m-files when we install our Matlab program on a different computer. The downside is that our wrapper function will be stuck with the version of sendmail.m that we copied into it, and we’d lose any possible improvements that Mathworks may implement in future Matlab releases.

The basic idea for the second alternative, the sendEmail.m wrapper, is something like this (the top highlighted lines are the additions made to the original sendmail.m, with everything placed in sendEmail.m on the Matlab path):

function sendEmail(to,subject,theMessage,attachments)%SENDEMAIL Send e-mail wrapper (with HTML formatting) sendmail(to,subject,theMessage,attachments);  % The rest of this file is copied from %matlabroot%/toolbox/matlab/iofun/sendmail.m (with the modifications mentioned above): function sendmail(to,subject,theMessage,attachments) %SENDMAIL Send e-mail. % SENDMAIL(TO,SUBJECT,MESSAGE,ATTACHMENTS) sends an e-mail. TO is either a % character vector specifying a single address, or a cell array of character vector ...

We would then call the wrapper function as follows:

sendEmail('abc@gmail.com', 'email subject', 'regular text message'); % will send a regular text message sendEmail('abc@gmail.com', 'email subject', '<b><font color="blue">HTML-formatted</font> <i>message'); % HTML-formatted message

In this case, the code automatically infers HTML formatting based on whether the first character in the message body is a ‘<‘ character. Instead, we could just as easily have passed an additional input argument (isHtml) to our sendEmail wrapper function.

Hopefully, in some future Matlab release Mathworks will be kind enough to enable sending 21st-century HTML-formatted emails without needing such hacks. Until then, note that sendmail.m relies on standard non-GUI Java networking classes, which are expected to be supported far into the future, well after Java-based GUI may cease to be supported in Matlab. For this reason I believe that while it seems a bit tricky, the changes that I outlined in today’s post actually have a low risk of breaking in a future Matlab release.

Do you have some other advanced email feature that you use in your Matlab program by some crafty customization to sendmail? If so, please share it in a comment below.

]]>
https://undocumentedmatlab.com/blog/sending-html-emails-from-matlab/feed 1
MathWorks-solicited Java surveyhttps://undocumentedmatlab.com/blog/mathworks-solicited-java-survey https://undocumentedmatlab.com/blog/mathworks-solicited-java-survey#comments Wed, 22 Mar 2017 22:05:34 +0000 http://undocumentedmatlab.com/?p=6866

Related posts:
1. Minimize/maximize figure window Matlab figure windows can easily be maximized, minimized and restored using a bit of undocumented magic powder...
2. Types of undocumented Matlab aspects This article lists the different types of undocumented/unsupported/hidden aspects in Matlab...
3. FindJObj – find a Matlab component’s underlying Java object The FindJObj utility can be used to access and display the internal components of Matlab controls and containers. This article explains its uses and inner mechanism....
4. Matlab callbacks for Java events Events raised in Java code can be caught and handled in Matlab callback functions - this article explains how...

]]>
Over the years I’ve reported numerous uses for integrating Java components and functionality in Matlab. As I’ve also recently reported, MathWorks is apparently making a gradual shift away from standalone Java-based figures, toward browser-based web-enabled figures. As I surmised a few months ago, MathWorks has created dedicated surveys to solicit user feedbacks on the most important (and undocumented) non-compatible aspects of this paradigm change: one regarding users’ use of the javacomponent function, the other regarding the use of the figure’s JavaFrame property:

In MathWorks’ words:

In order to extend your ability to build MATLAB apps, we understand you sometimes need to make use of undocumented Java UI technologies, such as the JavaFrame property. In response to your needs, we are working to develop documented alternatives that address gaps in our app building offerings.

To help inform our work and plans, we would like to understand how you are using the JavaFrame property. Based on your understanding of how it is being used within your app, please take a moment to fill out the following survey. The survey will take approximately 1-2 minutes to finish.

I urge anyone who uses one or both of these features to let MathWorks know how you’re using them, so that they could incorporate that functionality into the core (documented) Matlab. The surveys are really short and to the point. If you wish to send additional information, please email George.Caia at mathworks.com.

The more feedback responses that MathWorks will get, the better it will be able to prioritize its R&D efforts for the benefit of all users, and the more likely are certain features to get a documented solution at some future release. If you don’t take the time now to tell MathWorks how you use these features in your code, don’t complain if and when they break in the future…

### My personal uses of these features

• Functionality:
• Figure: maximize/minimize/restore, enable/disable, always-on-top, toolbar controls, menu customizations (icons, tooltips, font, shortcuts, colors)
• Table: sorting, filtering, grouping, column auto-sizing, cell-specific behavior (tooltip, context menu, context-sensitive editor, merging cells)
• Tree control
• Listbox: cell-specific behavior (tooltip, context menu)
• Tri-state checkbox
• uicontrols in general: various event callbacks (e.g. mouse hover/unhover, focus gained/lost)
• Ability to add Java controls e.g. color/font/date/file selector panel or dropdown, spinner, slider, search box, password field
• Ability to add 3rd-party components e.g. JFreeCharts, JIDE controls/panels

• Appearance:
• Figure: undecorated (frameless), other figure frame aspects
• Table: column/cell-specific rendering (alignment, icons, font, fg/bg color, string formatting)
• Listbox: auto-hide vertical scrollbar as needed, cell-specific renderer (icon, font, alignment, fg/bg color)
• Button/checkbox/radio: icons, text alignment, border customization, Look & Feel
• Right-aligned checkbox (button to the right of label)
• Panel: border customization (rounded/matte/…)

You can find descriptions/explanations of many of these in posts I made on this website over the years.

]]>
https://undocumentedmatlab.com/blog/mathworks-solicited-java-survey/feed 2
Password & spinner controls in Matlab GUIhttps://undocumentedmatlab.com/blog/password-and-spinner-controls-in-matlab-gui https://undocumentedmatlab.com/blog/password-and-spinner-controls-in-matlab-gui#comments Wed, 14 Dec 2016 17:28:09 +0000 http://undocumentedmatlab.com/?p=6775

Related posts:
1. Uitable sorting Matlab's uitables can be sortable using simple undocumented features...
2. Figure toolbar components Matlab's toolbars can be customized using a combination of undocumented Matlab and Java hacks. This article describes how to access existing toolbar icons and how to add non-button toolbar components....
3. Tab panels – uitab and relatives This article describes several undocumented Matlab functions that support tab-panels...
4. The javacomponent function Matlab's built-in javacomponent function can be used to display Java components in Matlab application - this article details its usages and limitations...

]]>
I often include configuration panels in my programs, to enable the user to configure various program aspects, such as which emails should automatically be sent by the program to alert when certain conditions occur. Last week I presented such a configuration panel, which is mainly composed of standard documented Matlab controls (sub-panels, uitables and uicontrols). As promised, today’s post will discuss two undocumented controls that are often useful in similar configuration panels (not necessarily for emails): password fields and spinners.

Matlab GUI configuration panel including password and spinner controls (click to zoom-in)

Password fields are basically editboxes that hide the typed text with some generic echo character (such as * or a bullet); spinners are editboxes that only enable typing certain preconfigured values (e.g., numbers in a certain range). Both controls are part of the standard Java Swing package, on which the current (non-web-based) Matlab GUIs relies. In both cases, we can use the javacomponent function to place the built-in Swing component in our Matlab GUI.

The relevant Java Swing control for password fields is javax.swing.JPasswordField. JPasswordField is basically an editbox that hides any typed key with a * or bullet character.

Here’s a basic code snippet showing how to display a simple password field:

jPasswordField = javax.swing.JPasswordField('defaultPassword'); % default password arg is optional jPasswordField = javaObjectEDT(jPasswordField); % javaObjectEDT is optional but recommended to avoid timing-related GUI issues jhPasswordField = javacomponent(jPasswordField, [10,10,70,20], gcf);

We can set/get the password string programmatically via the Text property; the displayed (echo) character can be set/get using the EchoChar property.

To attach a data-change callback, set jhPasswordField’s ActionPerformedCallback property.

### Spinner control

detailed post on using spinners in Matlab GUI

The relevant Java Swing control for spinners is javax.swing.JSpinner. JSpinner is basically an editbox with two tiny adjacent up/down buttons that visually emulate a small round spinning knob. 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. 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 0.1:

jModel = javax.swing.SpinnerNumberModel(24,20,35,0.1); jSpinner = javax.swing.JSpinner(jModel); jSpinner = javaObjectEDT(jSpinner); % javaObjectEDT is optional but recommended to avoid timing-related GUI issues jhSpinner = javacomponent(jSpinner, [10,10,70,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 various models have specific properties. For example, SpinnerNumberModel has the settable Maximum, Minimum and StepSize properties.

To attach a data-change callback, set jhSpinner’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 Java documentation. Readers are welcome to download this demo from the Matlab File Exchange and reuse its source code.

Matlab SpinnerDemo

The nice thing about spinners is that you can set a custom display format without affecting the underlying data model. For example, the following code snippet update the spinner’s display format without affecting its underlying numeric data model:

formatStr = '$#,##0.0 Bn'; jEditor = javaObject('javax.swing.JSpinner$NumberEditor', jhSpinner, formatStr); jhSpinner.setEditor(jEditor);

Formatted spinner control

For more information, refer to my detailed post on using spinners in Matlab GUI.

### Caveat emptor

MathWorks’ new web-based GUI paradigm will most probably not directly support the Java components presented in today’s post, or more specifically the javacomponent function that enables placing them in Matlab GUIs. The new web-based GUI-building application (AppDesigner, aka AD) does contain a spinner, although it is [currently] limited to displaying numeric values (not dates/lists as in my SpinnerDemo). Password fields are not currently supported by AppDesigner at all, and it is unknown whether they will ever be.

All this means that users of Java controls who wish to transition to the new web-based GUIs will need to develop programmatic workarounds, that would presumably appear and behave less professional. It’s a tradeoff: AppDesigner does include features that improve GUI usability, not to mention the presumed future ability to post Matlab GUIs online (hopefully without requiring a monstrous Matlab Production Server license/installation).

In the past, MathWorks has posted a dedicated webpage to solicit user feedback on how they are using the figure’s JavaFrame property. MathWorks will presumably prepare a similar webpage to solicit user feedback on uses of the javacomponent function, so they could add the top items to AppDesigner, making the transition to web-based GUIs less painful. When such a survey page becomes live, I will post about it on this website so that you could tell MathWorks about your specific use-cases and help them prioritize their R&D efforts.

In any case, regardless of whether the functionality eventually makes it into AppDesigner, my hope is that when the time comes MathWorks will not pull the plug from non-web GUIs, and will still enable running them on desktops for backward compatibility (“legacy mode”). Users of existing GUIs will then not need to choose between upgrading their Matlab (and redeveloping their GUI as a web-based app) and running their existing programs. Instead, users will face the much less painful choice between keeping the existing Java-based programs and developing a web-based variant at some later time, separate from the choice of whether or not to upgrade Matlab. The increased revenue from license upgrades and SMS (maintenance plan) renewals might well offset the R&D effort that would be needed to keep supporting the old Java-based figures. The traumatic* release of HG2 in R2014b, where a less-than-perfect version was released with no legacy mode, resulting in significant user backlash/disappointment, is hopefully still fresh in the memory of decision makers and would hopefully not be repeated.

*well, traumatic for some at least. I really don’t wish to make this a debate on HG2’s release; I’d rather focus on making the transition to web-based GUIs as seamless as possible.

]]>
Sending email/text messages from Matlabhttps://undocumentedmatlab.com/blog/sending-email-text-messages-from-matlab https://undocumentedmatlab.com/blog/sending-email-text-messages-from-matlab#comments Wed, 07 Dec 2016 21:24:03 +0000 http://undocumentedmatlab.com/?p=6765

Related posts:
1. Types of undocumented Matlab aspects This article lists the different types of undocumented/unsupported/hidden aspects in Matlab...
2. Legend ‘-DynamicLegend’ semi-documented feature The built-in Matlab legend function has a very useful semi-documented feature for automatic dynamic update, which is explained here....
3. Undocumented XML functionality Matlab's built-in XML-processing functions have several undocumented features that can be used by Java-savvy users...
4. Inactive Control Tooltips & Event Chaining Inactive Matlab uicontrols cannot normally display their tooltips. This article shows how to do this with a combination of undocumented Matlab and Java hacks....

]]>
In this day and age, applications are expected to communicate with users by sending email/text messages to alert them about applicative events (“IBM stock purchased @$99.99” or “House is on fire!”). Matlab has included the sendmail function to handle this for many years. Unfortunately, sendmail requires some tweaking to be useful on all but the most basic/insecure mail servers. Today’s post will hopefully fill the missing gaps. None of the information I’ll present today is really new – it was all there already if you just knew what to search for online. But hopefully today’s post will concentrate all these loose ends in a single place, so it may have some value: ### Using a secure mail server All modern mail servers use end-to-end TLS/SSL encryption. The sendmail function needs extra configuration to handle such connections, since it is configured for a non-encrypted connection by default. Here’s the code that does this for gmail, using SMTP server smtp.gmail.com and default port #465 (for other SMTP servers, see here): setpref('Internet', 'SMTP_Server', 'smtp.gmail.com'); setpref('Internet', 'SMTP_Username', username); setpref('Internet', 'SMTP_Password', password); props = java.lang.System.getProperties; props.setProperty('mail.smtp.auth', 'true'); % Note: 'true' as a string, not a logical value! props.setProperty('mail.smtp.starttls.enable', 'true'); % Note: 'true' as a string, not a logical value! props.setProperty('mail.smtp.socketFactory.port', '465'); % Note: '465' as a string, not a numeric value! props.setProperty('mail.smtp.socketFactory.class', 'javax.net.ssl.SSLSocketFactory'); sendmail(recipient, title, body, attachments); % e.g., sendmail('recipient@gmail.com', 'Hello world', 'What a nice day!', 'C:\images\sun.jpg') All this is not enough to enable Matlab to connect to gmail’s SMTP servers. In addition, we need to set the Google account to allow access from “less secure apps” (details, direct link). Without this, Google will not allow Matlab to relay emails. Other mail servers may require similar server-side account configurations to enable Matlab’s access. Note: This code snippet uses a bit of Java as you can see. Under the hood, all networking code in Matlab relies on Java, and sendmail is no exception. For some reason that I don’t fully understand, MathWorks chose to label the feature of using sendmail with secure mail servers as a feature that relies on “undocumented commands” and is therefore not listed in sendmail‘s documentation. Considering the fact that all modern mail servers are secure, this seems to make sendmail rather useless without the undocumented extension. I assume that TMW are well aware of this, which is the reason they posted a partial documentation in the form of an official tech-support answer. I hope that one day MathWorks will incorporate it into sendmail as optional input args, so that using sendmail with secure servers would become fully documented and officially supported. ### Emailing multiple recipients To specify multiple email recipients, it is not enough to set sendmail‘s recipient input arg to a string with , or ; delimiters. Instead, we need to provide a cell array of individual recipient strings. For example: sendmail({'recipient1@gmail.com','recipient2@gmail.com'}, 'Hello world', 'What a nice day!') Note: this feature is actually fully documented in sendmail‘s doc-page, but for some reason I see that some users are not aware of it (to which it might be said: RTFM!). ### Sending text messages With modern smartphones, text (SMS) messages have become rather outdated, as most users get push notifications of incoming emails. Still, for some users text messages may still be a useful. To send such messages, all we need is to determine our mobile carrier’s email gateway for SMS messages, and send a simple text message to that email address. For example, to send a text message to T-Mobile number 123-456-7890 in the US, simply email the message to 1234567890@tmomail.net (details). Ke Feng posted a nice Matlab File Exchange utility that wraps this messaging for a wide variety of US carriers. ### User configuration panel Many GUI programs contain configuration panels/tabs/windows. Enabling the user to set up their own email provider is a typical use-case for such a configuration. Naturally, you’d want your config panel not to display plain-text password, nor non-integer port numbers. You’d also want the user to be able to test the email connection. Here’s a sample implementation for such a panel that I implemented for a recent project – I plan to discuss the implementation details of the password and port (spinner) controls in my next post, so stay tuned: User configuration of emails in Matlab GUI (click to zoom-in) ]]> https://undocumentedmatlab.com/blog/sending-email-text-messages-from-matlab/feed 5 Speeding up Matlab-JDBC SQL querieshttps://undocumentedmatlab.com/blog/speeding-up-matlab-jdbc-sql-queries https://undocumentedmatlab.com/blog/speeding-up-matlab-jdbc-sql-queries#comments Wed, 16 Nov 2016 11:43:17 +0000 http://undocumentedmatlab.com/?p=6742   Related posts: 1. Using SQLite in Matlab SQLite databases can be accessed in a variety of different ways in Matlab. ... 2. Borderless button used for plot properties A borderless button can be used to add unobtrusive functionality to plot axes... 3. Matlab-Java memory leaks, performance Internal fields of Java objects may leak memory - this article explains how to avoid this without sacrificing performance. ... 4. File deletion memory leaks, performance Matlab's delete function leaks memory and is also slower than the equivalent Java function. ...   ]]> Many of my consulting projects involve interfacing a Matlab program to an SQL database. In such cases, using MathWorks’ Database Toolbox is a viable solution. Users who don’t have the toolbox can also easily connect directly to the database using either the standard ODBC bridge (which is horrible for performance and stability), or a direct JDBC connection (which is also what the Database Toolbox uses under the hood). I explained this Matlab-JDBC interface in detail in chapter 2 of my Matlab-Java programming book. A bare-bones implementation of an SQL SELECT query follows (data update queries are a bit different and will not be discussed here): % Load the appropriate JDBC driver class into Matlab's memory % (but not directly, to bypass JIT pre-processing - we must do it in run-time!) driver = eval('com.mysql.jdbc.Driver'); % or com.microsoft.sqlserver.jdbc.SQLServerDriver or whatever % Connect to DB dbPort = '3306'; % mySQL=3306; SQLServer=1433; Oracle=... connectionStr = ['jdbc:mysql://' dbURL ':' dbPort '/' schemaName]; % or ['jdbc:sqlserver://' dbURL ':' dbPort ';database=' schemaName ';'] or whatever dbConnObj = java.sql.DriverManager.getConnection(connectionStr, username, password); % Send an SQL query statement to the DB and get the ResultSet stmt = dbConnObj.createStatement(java.sql.ResultSet.TYPE_SCROLL_INSENSITIVE, java.sql.ResultSet.CONCUR_READ_ONLY); try stmt.setFetchSize(1000); catch, end % the default fetch size is ridiculously small in many DBs rs = stmt.executeQuery(sqlQueryStr); % Get the column names and data-types from the ResultSet's meta-data MetaData = rs.getMetaData; numCols = MetaData.getColumnCount; data = cell(0,numCols); % initialize for colIdx = numCols : -1 : 1 ColumnNames{colIdx} = char(MetaData.getColumnLabel(colIdx)); ColumnType{colIdx} = char(MetaData.getColumnClassName(colIdx)); % http://docs.oracle.com/javase/7/docs/api/java/sql/Types.html end ColumnType = regexprep(ColumnType,'.*\.',''); % Get the data from the ResultSet into a Matlab cell array rowIdx = 1; while rs.next % loop over all ResultSet rows (records) for colIdx = 1 : numCols % loop over all columns in the row switch ColumnType{colIdx} case {'Float','Double'} data{rowIdx,colIdx} = rs.getDouble(colIdx); case {'Long','Integer','Short','BigDecimal'} data{rowIdx,colIdx} = double(rs.getDouble(colIdx)); case 'Boolean' data{rowIdx,colIdx} = logical(rs.getBoolean(colIdx)); otherwise %case {'String','Date','Time','Timestamp'} data{rowIdx,colIdx} = char(rs.getString(colIdx)); end end rowIdx = rowIdx + 1; end % Close the connection and clear resources try rs.close(); catch, end try stmt.close(); catch, end try dbConnObj.closeAllStatements(); catch, end try dbConnObj.close(); catch, end % comment this to keep the dbConnObj open and reuse it for subsequent queries Naturally, in a real-world implementation you also need to handle database timeouts and various other errors, handle data-manipulation queries (not just SELECTs), etc. Anyway, this works well in general, but when you try to fetch a ResultSet that has many thousands of records you start to feel the pain – The SQL statement may execute much faster on the DB server (the time it takes for the stmt.executeQuery call), yet the subsequent double-loop processing to fetch the data from the Java ResultSet object into a Matlab cell array takes much longer. In one of my recent projects, performance was of paramount importance, and the DB query speed from the code above was simply not good enough. You might think that this was due to the fact that the data cell array is not pre-allocated, but this turns out to be incorrect: the speed remains nearly unaffected when you pre-allocate data properly. It turns out that the main problem is due to Matlab’s non-negligible overhead in calling methods of Java objects. Since the JDBC interface only enables retrieving a single data item at a time (in other words, bulk retrieval is not possible), we have a double loop over all the data’s rows and columns, in each case calling the appropriate Java method to retrieve the data based on the column’s type. The Java methods themselves are extremely efficient, but when you add Matlab’s invocation overheads the total processing time is much much slower. So what can be done? As Andrew Janke explained in much detail, we basically need to push our double loop down into the Java level, so that Matlab receives arrays of primitive values, which can then be processed in a vectorized manner in Matlab. So let’s create a simple Java class to do this: // Copyright (c) Yair Altman UndocumentedMatlab.com import java.sql.ResultSet; import java.sql.ResultSetMetaData; import java.sql.SQLException; import java.sql.Types; public class JDBC_Fetch { public static int DEFAULT_MAX_ROWS = 100000; // default cache size = 100K rows (if DB does not support non-forward-only ResultSets) public static Object[] getData(ResultSet rs) throws SQLException { try { if (rs.last()) { // data is available int numRows = rs.getRow(); // row # of the last row rs.beforeFirst(); // get back to the top of the ResultSet return getData(rs, numRows); // fetch the data } else { // no data in the ResultSet return null; } } catch (Exception e) { return getData(rs, DEFAULT_MAX_ROWS); } } public static Object[] getData(ResultSet rs, int maxRows) throws SQLException { // Read column number and types from the ResultSet's meta-data ResultSetMetaData metaData = rs.getMetaData(); int numCols = metaData.getColumnCount(); int[] colTypes = new int[numCols+1]; int numDoubleCols = 0; int numBooleanCols = 0; int numStringCols = 0; for (int colIdx = 1; colIdx <= numCols; colIdx++) { int colType = metaData.getColumnType(colIdx); switch (colType) { case Types.FLOAT: case Types.DOUBLE: case Types.REAL: colTypes[colIdx] = 1; // double numDoubleCols++; break; case Types.DECIMAL: case Types.INTEGER: case Types.TINYINT: case Types.SMALLINT: case Types.BIGINT: colTypes[colIdx] = 1; // double numDoubleCols++; break; case Types.BIT: case Types.BOOLEAN: colTypes[colIdx] = 2; // boolean numBooleanCols++; break; default: // 'String','Date','Time','Timestamp',... colTypes[colIdx] = 3; // string numStringCols++; } } // Loop over all ResultSet rows, reading the data into the 2D matrix caches int rowIdx = 0; double [][] dataCacheDouble = new double [numDoubleCols] [maxRows]; boolean[][] dataCacheBoolean = new boolean[numBooleanCols][maxRows]; String [][] dataCacheString = new String [numStringCols] [maxRows]; while (rs.next() && rowIdx < maxRows) { int doubleColIdx = 0; int booleanColIdx = 0; int stringColIdx = 0; for (int colIdx = 1; colIdx <= numCols; colIdx++) { try { switch (colTypes[colIdx]) { case 1: dataCacheDouble[doubleColIdx++][rowIdx] = rs.getDouble(colIdx); break; // numeric case 2: dataCacheBoolean[booleanColIdx++][rowIdx] = rs.getBoolean(colIdx); break; // boolean default: dataCacheString[stringColIdx++][rowIdx] = rs.getString(colIdx); break; // string } } catch (Exception e) { System.out.println(e); System.out.println(" in row #" + rowIdx + ", col #" + colIdx); } } rowIdx++; } // Return only the actual data in the ResultSet int doubleColIdx = 0; int booleanColIdx = 0; int stringColIdx = 0; Object[] data = new Object[numCols]; for (int colIdx = 1; colIdx <= numCols; colIdx++) { switch (colTypes[colIdx]) { case 1: data[colIdx-1] = dataCacheDouble[doubleColIdx++]; break; // numeric case 2: data[colIdx-1] = dataCacheBoolean[booleanColIdx++]; break; // boolean default: data[colIdx-1] = dataCacheString[stringColIdx++]; // string } } return data; } } So now we have a JDBC_Fetch class that we can use in our Matlab code, replacing the slow double loop with a single call to JDBC_Fetch.getData(), followed by vectorized conversion into a Matlab cell array (matrix): % Get the data from the ResultSet using the JDBC_Fetch wrapper data = cell(JDBC_Fetch.getData(rs)); for colIdx = 1 : numCols switch ColumnType{colIdx} case {'Float','Double'} data{colIdx} = num2cell(data{colIdx}); case {'Long','Integer','Short','BigDecimal'} data{colIdx} = num2cell(data{colIdx}); case 'Boolean' data{colIdx} = num2cell(data{colIdx}); otherwise %case {'String','Date','Time','Timestamp'} %data{colIdx} = cell(data{colIdx}); % no need to do anything here! end end data = [data{:}]; On my specific program the resulting speedup was 15x (this is not a typo: 15 times faster). My fetches are no longer limited by the Matlab post-processing, but rather by the DB’s processing of the SQL statement (where DB indexes, clustering, SQL tuning etc. come into play). Additional speedups can be achieved by parsing dates at the Java level (rather than returning strings), as well as several other tweaks in the Java and Matlab code (refer to Andrew Janke’s post for some ideas). But certainly the main benefit (the 80% of the gain that was achieved in 20% of the worktime) is due to the above push of the main double processing loop down into the Java level, leaving Matlab with just a single Java call to JDBC_Fetch. Many additional ideas of speeding up database queries and Matlab programs in general can be found in my second book, Accelerating Matlab Performance. If you’d like me to help you speed up your Matlab program, please email me (altmany at gmail), or fill out the query form on my consulting page. ]]> https://undocumentedmatlab.com/blog/speeding-up-matlab-jdbc-sql-queries/feed 6 Working with non-standard DPI displayshttps://undocumentedmatlab.com/blog/working-with-non-standard-dpi-displays https://undocumentedmatlab.com/blog/working-with-non-standard-dpi-displays#comments Wed, 09 Nov 2016 21:47:27 +0000 http://undocumentedmatlab.com/?p=6736   Related posts: 1. FindJObj – find a Matlab component’s underlying Java object The FindJObj utility can be used to access and display the internal components of Matlab controls and containers. This article explains its uses and inner mechanism.... 2. FindJObj GUI – display container hierarchy The FindJObj utility can be used to present a GUI that displays a Matlab container's internal Java components, properties and callbacks.... 3. Blurred Matlab figure window Matlab figure windows can be blurred using a semi-transparent overlaid window - this article explains how... 4. Customizing figure toolbar background Setting the figure toolbar's background color can easily be done using just a tiny bit of Java magic powder. This article explains how. ...   ]]> With high-density displays becoming increasingly popular, some users set their display’s DPI to a higher-than-standard (i.e., >100%) value, in order to compensate for the increased pixel density to achieve readable interfaces. This OS setting tells the running applications that there are fewer visible screen pixels, and these are spread over a larger number of physical pixels. This works well for most cases (at least on recent OSes, it was a bit buggy in non-recet ones). Unfortunately, in some cases we might actually want to know the screen size in physical, rather than logical, pixels. Apparently, Matlab root’s ScreenSize property only reports the logical (scaled) pixel size, not the physical (unscaled) one: >> get(0,'ScreenSize') % with 100% DPI (unscaled standard) ans = 1 1 1366 768 >> get(0,'ScreenSize') % with 125% DPI (scaled) ans = 1 1 1092.8 614.4 The same phenomenon also affects other related properties, for example MonitorPositions. Raimund Schlüßler, a reader on this blog, was kind enough to point me to this problem and its workaround, which I thought worthy to share here: To get the physical screen-size, use the following builtin Java command: >> jScreenSize = java.awt.Toolkit.getDefaultToolkit.getScreenSize jScreenSize = java.awt.Dimension[width=1366,height=768] >> width = jScreenSize.getWidth width = 1366 >> height = jScreenSize.getHeight height = 768 Also see the related recent article on an issue with the DPI-aware feature starting with R2015b. ### Upcoming travels – London/Belfast, Zürich & Geneva I will shortly be traveling to consult some clients in Belfast (via London), Zürich and Geneva. If you are in the area and wish to meet me to discuss how I could bring value to your work, then please email me (altmany at gmail): • Belfast: Nov 28 – Dec 1 (flying via London) • Zürich: Dec 11-12 • Geneva: Dec 13-15 ]]> https://undocumentedmatlab.com/blog/working-with-non-standard-dpi-displays/feed 6 uigetfile/uiputfile customizationshttps://undocumentedmatlab.com/blog/uigetfile-uiputfile-customizations https://undocumentedmatlab.com/blog/uigetfile-uiputfile-customizations#comments Wed, 02 Nov 2016 23:38:57 +0000 http://undocumentedmatlab.com/?p=6728   Related posts: 1. Plot-type selection components Several built-in components enable programmatic plot-type selection in Matlab GUI - this article explains how... 2. Uitable sorting Matlab's uitables can be sortable using simple undocumented features... 3. Animated busy (spinning) icon An animated spinning icon label can easily be embedded in Matlab GUI. ... 4. Auto-completion widget Matlab includes a variety of undocumented internal controls that can be used for an auto-completion component. ...   ]]> Matlab includes a few built-in file and folder selection dialog windows, namely uigetfile, uiputfile and uigetdir. Unfortunately, these functions are not easily extendable for user-defined functionalities. Over the years, several of my consulting clients have asked me to provide them with versions of these dialog functions that are customized in certain ways. In today’s post I discuss a few of these customizations: a file selector dialog with a preview panel, and automatic folder update as-you-type in the file-name edit box. It is often useful to have an integrated preview panel to display the contents of a file in a file-selection dialog. Clicking the various files in the tree-view would display a user-defined preview in the panel below, based on the file’s contents. An integrated panel avoids the need to manage multiple figure windows, one for the selector dialog and another for the preview. It also reduces the screen real-estate used by the dialog (also see the related resizing customization below). I call the end-result uigetfile_with_preview; you can download it from the Matlab File Exchange: filename = uigetfile_with_preview(filterSpec, prompt, folder, callbackFunction, multiSelectFlag) As you can see from the function signature, the user can specify the file-type filter, prompt and initial folder (quite similar to uigetfile, uiputfile), as well as a custom callback function for updating the preview of a selected file, and a flag to enable selecting multiple files (not just one). uigetfile_with_preview.m only has ~120 lines of code and plenty of comments, so feel free to download and review the code. It uses the following undocumented aspects: 1. I used a com.mathworks.hg.util.dFileChooser component for the main file selector. This is a builtin Matlab control that extends the standard javax.swing.JFileChooser with a few properties and methods. I don’t really need the extra features, so you can safely replace the component with a JFileChooser if you wish (lines 54-55). Various properties of the file selector are then set, such as the folder that is initially displayed, the multi-selection flag, the component background color, and the data-type filter options. 2. I used the javacomponent function to place the file-selector component within the dialog window. 3. I set a callback on the component’s PropertyChangeCallback that is invoked whenever the user interactively selects a new file. This callback clears the preview panel and then calls the user-defined callback function (if available). 4. I set a callback on the component’s ActionPerformedCallback that is invoked whenever the user closes the figure or clicks the “Open” button. The selected filename(s) is/are then returned to the caller and the dialog window is closed. 5. I set a callback on the component’s file-name editbox’s KeyTypedCallback that is invoked whenever the user types in the file-name editbox. The callback checks whether the entered text looks like a valid folder path and if so then it automatically updates the displayed folder as-you-type. If you want to convert the code to a uiputfile variant, add the following code lines before the uiwait in line 111: hjFileChooser.setShowOverwriteDialog(true); % default: false (true will display a popup alert if you select an existing file) hjFileChooser.setDialogType(hjFileChooser.java.SAVE_DIALOG); % default: OPEN_DIALOG hjFileChooser.setApproveButtonText('Save'); % or any other string. Default for SAVE_DIALOG: 'Save' hjFileChooser.setApproveButtonToolTipText('Save file'); % or any other string. Default for SAVE_DIALOG: 'Save selected file' In memory of my dear father. ]]> https://undocumentedmatlab.com/blog/uigetfile-uiputfile-customizations/feed 2 Listbox selection hackshttps://undocumentedmatlab.com/blog/listbox-selection-hacks https://undocumentedmatlab.com/blog/listbox-selection-hacks#comments Wed, 13 Jul 2016 15:36:19 +0000 http://undocumentedmatlab.com/?p=6534   Related posts: 1. Editbox data input validation Undocumented features of Matlab editbox uicontrols enable immediate user-input data validation... 2. Continuous slider callback Matlab slider uicontrols do not enable a continuous-motion callback by default. This article explains how this can be achieved using undocumented features.... 3. Matlab and the Event Dispatch Thread (EDT) The Java Swing Event Dispatch Thread (EDT) is very important for Matlab GUI timings. This article explains the potential pitfalls and their avoidance using undocumented Matlab functionality.... 4. Customizing combobox popups Matlab combobox (dropdown) popups can be customized in a variety of ways. ...   ]]> Last week a reader on the CSSM newsgroup asked whether it is possible to programmatically deselect all listbox items. By default, Matlab listboxes enable a single item selection: trying to deselect it interactively has no effect, while trying to set the listbox’s Value property to empty ([]) results in the listbox disappearing and a warning issued to the Matlab console: >> hListbox = uicontrol('Style','list', 'String',{'item #1','item #2','item #3','item #4','item #5','item #6'}); >> set(hListbox,'Value',[]); Warning: Single-selection 'listbox' control requires a scalar Value. Control will not be rendered until all of its parameter values are valid (Type "warning off MATLAB:hg:uicontrol:ValueMustBeScalar" to suppress this warning.) The reader’s question was whether there is a way to bypass this limitation so that no listbox item will be selected. The answer to this question was provided by MathWorker Steve(n) Lord. Steve is a very long-time benefactor of the Matlab community with endless, tireless, and patient advise to queries small and large (way beyond the point that would have frustrated mere mortals). Steve pointed out that by default, Matlab listboxes only enable a single selection – not more and not less. However, when the listbox’s Max value is set to be >1, the listbox enables multiple-items selection, meaning that Value accepts and reports an array of item indices, and there is nothing that prevents this array from being empty (meaning no items selected): >> hListbox = uicontrol('Style','list', 'Max',2, 'String',{'item #1','item #2','item #3','item #4','item #5','item #6'}); >> set(hListbox,'Value',[]); % this is ok - listbox appears with no items selected Note: actually, the listbox checks the value of MaxMin, but by default Min=0 and there is really no reason to modify this default value, just Max. While this makes sense if you think about it, the existing documentation makes no mention of this fact: The Max property value helps determine whether the user can select multiple items in the list box simultaneously. If Max – Min > 1, then the user can select multiple items simultaneously. Otherwise, the user cannot select multiple items simultaneously. If you set the Max and Min properties to allow multiple selections, then the Value property value can be a vector of indices. Some readers might think that this feature is not really undocumented, since it does not directly conflict with the documentation text, but then so are many other undocumented aspects and features on this blog, which are not mentioned anywhere in the official documentation. I contend that if this feature is officially supported, then it deserves an explicit sentence in the official documentation. However, the original CSSM reader wanted to preserve Matlab’s single-selection model while enabling deselection of an item. Basically, the reader wanted a selection model that enables 0 or 1 selections, but not 2 or more. This requires some tweaking using the listbox’s selection callback: set(hListbox,'Callback',@myCallbackFunc); ... function test(hListbox, eventData) value = get(hListbox, 'Value'); if numel(value) > 1 set(hListbox, 'Value', value(1)); end end …or a callback-function version that is a bit better because it takes the previous selection into account and tries to set the new selection to the latest-selected item (this works in most cases, but not with shift-clicks as explained below): function myCallbackFunc(hListbox, eventData) lastValue = getappdata(hListbox, 'lastValue'); value = get(hListbox, 'Value'); if ~isequal(value, lastValue) value2 = setdiff(value, lastValue); if isempty(value2) setappdata(hListbox, 'lastValue', value); else value = value2(1); % see quirk below setappdata(hListbox, 'lastValue', value); set(hListbox, 'Value', value); end end end This does the job of enabling only a single selection at the same time as allowing the user to interactively deselect that item (by ctrl-clicking it). There’s just a few quirks: If the user selects a block of items (using shift-click), then only the second-from-top item in the block is selected, rather than the expected last-selected item. This is due to line #9 in the callback code which selects the first value. Matlab does not provide us with information about which item was clicked, so this cannot be helped using pure Matlab. Another quirk that cannot easily be solved using pure Matlab is the flicker that occurs when the selection changes and is then corrected by the callback. We can solve both of these problems using the listbox’s underlying Java component, which we can retrieve using my findjobj utility: % No need for the standard Matlab callback now set(hListbox,'Callback',[]); % Get the underlying Java component peer jScrollPane = findjobj(h); jListbox = jScrollPane.getViewport.getView; jListbox = handle(jListbox,'CallbackProperties'); % enable callbacks % Attach our callback to the listbox's Java peer jListbox.ValueChangedCallback = {@myCallbackFunc, hListbox}; ... function myCallbackFunc(jListbox, eventData, hListbox) if numel(jListbox.getSelectedIndices) > 1 set(hListbox, 'Value', jListbox.getLeadSelectionIndex+1); % +1 because Java indices start at 0 end end We can use a similar mechanism to control other aspects of selection, for example to enable only up to 3 selections but no more etc. We can use this underlying Java component peer for a few other useful selection-related hacks: First, we can use the peer’s RightSelectionEnabled property or setRightSelectionEnabled() method to enable the user to select by right-clicking listbox items (this is disabled by default): jListbox.setRightSelectionEnabled(true); % false by default set(jListbox,'RightSelectionEnabled',true); % equivalent alternative A similarly useful property is DragSelectionEnabled (or the corresponding setDragSelectionEnabled() method), which is true by default, and controls whether the selection is extended to other items when the mouse drags an item up or down the listbox. Finally, we can control whether in multi-selection mode we enable the user to only select a single contiguous block of items, or not (which is Matlab’s default behavior). This is set via the SelectionMode property (or associated setSelectionMode() method), as follows: jListbox.setSelectionMode(javax.swing.ListSelectionModel.SINGLE_INTERVAL_SELECTION); jListbox.setSelectionMode(1); % equivalent alternative (less maintainable/readable, but simpler)  SINGLE_SELECTION =0 SINGLE_INTERVAL_SELECTION =1 MULTIPLE_INTERVAL_SELECTION =2 (Matlab default for Max=1) (only possible with Java) (Matlab default for Max>1) Additional listbox customizations can be found in related posts on this blog (see links below), or in section 6.6 of my Matlab-Java Programming Secrets book (which is still selling nicely almost five years after its publication, to the pleasant surprise of my publisher…). ]]> https://undocumentedmatlab.com/blog/listbox-selection-hacks/feed 4 Handling red Java console errorshttps://undocumentedmatlab.com/blog/handling-red-java-console-errors https://undocumentedmatlab.com/blog/handling-red-java-console-errors#comments Wed, 29 Jun 2016 17:00:51 +0000 http://undocumentedmatlab.com/?p=6468   Related posts: 1. Setting system tray icons System-tray icons can be programmatically set and controlled from within Matlab, using new functionality available since R2007b.... 2. Setting system tray popup messages System-tray icons and messages can be programmatically set and controlled from within Matlab, using new functionality available since R2007b.... 3. JGit-Matlab integration JGit source-control integration package can easily be integrated in Matlab. ... 4. Non-textual editor actions The UIINSPECT utility can be used to expand EditorMacro capabilities to non-text-insertion actions. This is how:...   ]]> Anyone who has worked with non-trivial Matlab GUIs knows that from time to time we see various red Java stack-trace errors appear in the Matlab console (Command Window). These errors do not appear often when using documented Matlab controls, but they do from time to time. The errors appear significantly more frequently when working with undocumented Java-based hacks that I often show on this blog, and especially when working with complex controls such as uitable or uitree. Such controls have a very large code-base under the hood, and the Matlab code and data sometimes clashes with the asynchronous Java methods that run on a separate thread. Such clashes and race conditions often lead to red Java stack-trace errors that are spewed onto the Matlab console. For example: Exception in thread "AWT-EventQueue-0" java.lang.NullPointerException at com.jidesoft.plaf.basic.BasicCellSpanTableUI.paint(Unknown Source) at javax.swing.plaf.ComponentUI.update(Unknown Source) at javax.swing.JComponent.paintComponent(Unknown Source) at com.jidesoft.grid.CellStyleTable.paintComponent(Unknown Source) at javax.swing.JComponent.paint(Unknown Source) at javax.swing.JComponent.paintToOffscreen(Unknown Source) ... Exception in thread "AWT-EventQueue-0" java.lang.ArrayIndexOutOfBoundsException: 1 >= 0 at java.util.Vector.elementAt(Unknown Source) at javax.swing.table.DefaultTableColumnModel.getColumn(Unknown Source) at com.jidesoft.grid.ContextSensitiveTable.getCellRenderer(Unknown Source) at com.jidesoft.grid.CellSpanTable.getCellRenderer(Unknown Source) at com.jidesoft.grid.TreeTable.getActualCellRenderer(Unknown Source) at com.jidesoft.grid.GroupTable.getCellRenderer(Unknown Source) at com.jidesoft.grid.JideTable.b(Unknown Source) at com.jidesoft.grid.CellSpanTable.calculateRowHeight(Unknown Source) ...  In almost all such Java error messages, the error is asynchronous to the Matlab code and does not interrupt it. No error exception is thrown (or can be trapped), and the Matlab code proceeds without being aware that anything is wrong. In fact, in the vast majority of such cases, nothing is visibly wrong – the program somehow overcomes the reported problem and there are no visible negative effects on the GUI. In other words, these error messages are harmless and can almost always be ignored. Still, if we could only stop those annoying endless red stack-trace messages in the Matlab console! Note that today’s post only discusses untrappable asynchronous Java error messages, not synchronous errors that can be trapped in Matlab via try-catch. These synchronous errors are often due to programmatic errors (e.g., bad method input args or an empty reference handle) and can easily be handled programmatically. On the other hand, the asynchronous errors are non-trappable, so they are much more difficult to isolate and fix. In many of the cases, the error occurs when the control’s underlying data model is changed by the Matlab code, and some of the controls’s Java methods are not synced with the new model by the time they run. This can be due to internal bugs in the Matlab or Java control’s implementation, or to simple race conditions that occur between the Matlab thread and the Java Event Dispatch Thread (EDT). As noted here, such race conditions can often be solved by introducing a simple delay into the Matlab code: javaControl.doSomething(); pause(0.05); drawnow;javaControl.doSomethingElse(); In addition, asking Matlab to run the Java component’s methods on the EDT can also help solve race conditions: javaControl = javaObjectEDT(javaControl); Unfortunately, sometimes both of these are not enough. In such cases, one of the following ideas might help: • Add fprintf(' \b') to your Matlab code: this seemingly innocent hack of displaying a space & immediately erasing it with backspace, appears to force the Java engine to flush its event queue and synchronize things, thereby avoiding the annoying Java console errors. I know it sounds like adding a sprinkle of useless black magic to the code, but it does really work in some cases! javaControl.doSomething(); pause(0.05); drawnow; % this never hurt anyone! fprintf(' \b');javaControl.doSomethingElse(); • It is also possible to directly access the console text area and remove all the text after a certain point. Note that I strongly discourage messing around with the console text in this manner, since it might cause problems with Matlab’s internals. Still, if you are adventurous enough to try, then here’s an example: jCmdWinDoc = com.mathworks.mde.cmdwin.CmdWinDocument.getInstance; currentPos = cmdWinDoc.getLength; javaControl.doSomething(); pause(0.05); drawnow; % this never hurt anyone! javaControl.doSomethingElse(); pause(0.1); % let the java error time to display itself in the console jCmdWinDoc.remove(currentPos, cmdWinDoc.getLength-currentPos); • When all else fails, consider simply clearing the Matlab console using the Matlab clc command a short while after updating the Java control. This will erase the red Java errors, along with everything else in the console, so naturally it cannot be freely used if you use the console to display useful information to the user. It should be emphasized: not all of these suggested remedies work in all cases; in some cases some of them work, and in other cases others might work. There does not seem to be a general panacea to this issue. The main purpose of the article was to list the possible solutions in a single place, so that users could try them out and select those that work for each specific case. Do you know of any other (perhaps better) way of avoiding or hiding such asynchronous Java console errors? If so, then please post a comment below. ]]> https://undocumentedmatlab.com/blog/handling-red-java-console-errors/feed 6 Figure window customizationshttps://undocumentedmatlab.com/blog/figure-window-customizations https://undocumentedmatlab.com/blog/figure-window-customizations#respond Wed, 01 Jun 2016 08:00:11 +0000 http://undocumentedmatlab.com/?p=6439   Related posts: 1. Minimize/maximize figure window Matlab figure windows can easily be maximized, minimized and restored using a bit of undocumented magic powder... 2. FindJObj – find a Matlab component’s underlying Java object The FindJObj utility can be used to access and display the internal components of Matlab controls and containers. This article explains its uses and inner mechanism.... 3. Uitable sorting Matlab's uitables can be sortable using simple undocumented features... 4. Frameless (undecorated) figure windows Matlab figure windows can be made undecorated (borderless, title-less). ...   ]]> A friend recently asked me, in light of my guesstimate that Java-based Matlab figures will be replaced by web-based figures sometime around 2018-2020, whether there are any “killer features” that make it worthwhile to use undocumented Java-based tricks today, despite the fact that they will probably break in 2-5 years. In my opinion, there are many such features; today I will focus on just a subset of them – those features that relate to the entire figure window. Over the years I wrote many articles here about figure-level customizations, as well as an entire chapter in my Matlab-Java programming book. So today’s post will be a high-level overview, and users who are interested in any specific topic can visit the referenced links for the implementation details. An undecorated Matlab figure window – one of many possible figure-level customizations ### JavaFrame JavaFrame is an undocumented hidden property of the figure handle that provides access to the underlying Java window (JFrame) peer object’s reference. Since R2008a, a warning is issued whenever we retrieve this property: >> jFrame = get(gcf,'JavaFrame'); Warning: figure JavaFrame property will be obsoleted in a future release. For more information see the JavaFrame resource on the MathWorks web site. (Type "warning off MATLAB:HandleGraphics:ObsoletedProperty:JavaFrame" to suppress this warning.)  Until HG2 (R2014b+) we could suppress the warning by simply wrapping the figure handle within a handle() call, as explained here. Since R2014b we need to use the warning function to do this: warning('off', 'MATLAB:HandleGraphics:ObsoletedProperty:JavaFrame'); We can do several things directly with the JavaFrame‘s properties and methods, including: • Maximize/minimize/restore the window, via the properties Maximized/Minimized (which accept and return a boolean (logical) value), or the corresponding methods jFrame.isMaximized(), isMinimized(), setMaximized(flag), setMinimized(flag). details • Modify the container to which the figure will be docked. By default this is the “Figures” container, but this can be changed to any user-specified container, or even to the “Editor”, using the GroupName property or its associated methods. See the related setFigDockGroup utility that I posted on the Matlab File exchange. • Remove the top separator line between the toolbar and the content-pane, to blend them together, via the jFrame.showTopSeparator(flag) method. • Retrieve a direct Java reference to the Matlab Desktop and the figure’s internal containers via the Desktop and FigurePanelContainer properties, respectively (we can also get those references by other means). • Retrieve a direct Java reference to the containing JFrame (Java window), as discussed below • A few other features that I will not discuss here MathWorks have set up a dedicated webpage where you can specify how you are using JavaFrame and why it is important for you: http://www.mathworks.com/javaframe. I encourage you to use this webpage to tell MathWorks which features are important for you. This will help them to decide which functionality should be added to the new web-based figures. ### JFrame window The JavaFrame handle enables direct retrieval of the containing Java JFrame (window) reference, using several alternatives. Here are two of these alternatives (there are others): % Alternative #1 >> jWindow = jFrame.getFigurePanelContainer.getTopLevelAncestor jWindow = com.mathworks.hg.peer.FigureFrameProxy$FigureFrame[fClientProxyFrame,72,62,576x507,...]   % Alternative #2 try jClient = jFrame.fFigureClient; % This works up to R2011a catch try jClient = jFrame.fHG1Client; % This works from R2008b-R2014a catch jClient = jFrame.fHG2Client; % This works from R2014b and up end end jWindow = jClient.getWindow;

Customized menu items (top) and figure status bar (bottom)

With the retrieved jWindow reference, we can do several additional interesting things:

• Enable/disable the entire figure in a single go (details)
• Remove/restore the window frame (borders and title bar), otherwise known as an “undecorated window” (details)
• Set the figure window to be “Always-On-Top”, i.e. not occluded by any other window, via the AlwaysOnTop property, or the corresponding jWindow.isAlwaysOnTop(), setAlwaysOnTop(flag) methods.
• Make the figure window fully or partially transparent (details). Note: this fails on R2013b/Java7 and higher due to a change in the way that transparency works in Java 7 compared to earlier releases; in other words blame Oracle’s Java, not MathWorks’ Matlab….
• Blur/restore the figure window (details). This too works only up to R2013a.
• Detect and handle window-level focus gain/loss events (details), as well as window-level mouse events (enter/exit/hover etc. – details).
• Customize the figure’s menu bar – dynamic behavior, tooltips, highlights, keyboard shortcuts/accelerators, font colors/styles, callbacks, icons etc. (details1, details2)
• Control figure docking in compiled (deployed) applications (details1, details2)
• Display an integral figure status-bar with text and GUI controls (details1, details2).
• A few other features that I will not discuss here

As you can see, there are numerous very interesting customizations that can be done to Matlab figures which rely on the undocumented implementation. Here are a couple of usage examples that you can easily adapt (follow the links above for additional details and usage examples):

jWindow.setEnabled(false); % disable entire figure [true/false] jWindow.setMinimized(true); % minimize window [true/false] jWindow.setMaximized(true); % maximize window [true/false] jWindow.setAlwaysOnTop(true); % set to be always on top [true/false]   % Set a Matlab callback function to a window focus-gain event hjWindow = handle(jWindow, 'CallbackProperties'); hjWindow.FocusGainedCallback = @myCallbackFunc;

In addition to the Java-based features above, some functionalities can also be achieved via direct OS manipulations, for example using Jan Simon’s great WindowAPI utility (Windows-only), although I typically prefer using the Java approach since it is cross-platform compatible.

Using all these features is super-easy, so there is not really a question of code complexity or technical risk – the main question is whether to accept the risk that the associated code will stop working when Matlab figures will eventually become web-based.

### So is it worth the risk?

This is an excellent question. I contend that the answer depends on the specific use-case. In one project you may decide that it is indeed worth-while to use these undocumented features today, whereas in another GUI you may decide that it is not.

It might make sense to use the features above in any of the following circumstances:

• If you need any of the features in your Matlab GUI today. In this case, you really have no alternative other than to use these features, since there is no documented way to achieve the required functionality.
• If you do not plan to upgrade your Matlab release soon, or at least after the Java-based figures are discontinued in a few years. The commercial Matlab license is perpetual, enabling users to enjoy these features for as long as they continue using this Matlab release.
• If you are compiling your Matlab program using the Matlab Compiler or Coder toolboxes. In such cases, the executable will remain static, until such time (if ever) that you decide to recompile it using a newer Matlab release. Users of the compiled code could continue to use the compiled undocumented features well into the future, for as long as their computers keep running. In such cases, we are not concerned with release compatibility issues.
• If you accept the risk that some recoding may be necessary in the future, or that some functionality will degrade, for the added benefit that they provide your GUIs today.
• If you are willing to code without MathWorks’ official support and endorsement, and accept the fact that they will not fix any internal bugs that you may discover which is related to these features.
• If you wish to present a professional-grade GUI today, and worry about potential incompatibilities only if and when they eventually arrive, sometime in the future.

Here’s another twist to consider: do not take it for granted that when web-based uifigures replace Java-based figures all the documented functionality will work as-is on the new uifigures just as they have on the old figures. In fact, I personally believe that we will need to extensively modify our GUI code to make it compatible with the new uifigures. In other words, avoiding the undocumented hacks above will probably not save us from the need to recode (or at least adapt) our GUI, it will just reduce the necessary work somewhat. We encountered a similar situation with the graphics hacks that I exposed over the years: many people avoided them in the fear that they might someday break; then when R2014b came and HG2 graphics replaced HG1, it turned out that many of these supposedly risky hacks continued working in HG2 (examples: LooseInset, YLimInclude) whereas quite a bit of standard fully-documented Matlab functionality was broken and required some recoding. I believe that the lessons from the HG2 migration were well studied and assimilated by MathWorks, but realistically speaking we should not expect a 100% full-proof transition to uifigures.

Still, accepting the risk does not mean that we should bury our head in the sand. Whenever using any undocumented feature in your code, I strongly suggest to use defensive coding practices, such as wrapping your code within try-catch blocks. This way, even if the feature is removed in R2020a (or whenever), the program will still run, albeit with somewhat diminished functionality, or in other words, graceful degradation. For example:

try jFrame = get(hFig, 'JavaFrame'); jFrame.setMaximized(true); catch oldUnits = get(hFig, 'Units'); set(hFig, 'Units','norm', 'Pos',[0,0,1,1]); set(hFig, 'Units',oldUnits); end

Once again, I urge you to visit http://www.mathworks.com/javaframe and tell MathWorks which of the above features are important for you. The more users tell MathWorks that they depend on a specific feature, the more would MathWorks be likely to invest R&D efforts in enabling it in the future web-based figures.

]]>
https://undocumentedmatlab.com/blog/figure-window-customizations/feed 0
Transparent labelshttps://undocumentedmatlab.com/blog/transparent-labels https://undocumentedmatlab.com/blog/transparent-labels#comments Wed, 04 May 2016 16:26:08 +0000 http://undocumentedmatlab.com/?p=6403

Related posts:
1. FindJObj – find a Matlab component’s underlying Java object The FindJObj utility can be used to access and display the internal components of Matlab controls and containers. This article explains its uses and inner mechanism....
2. Plot-type selection components Several built-in components enable programmatic plot-type selection in Matlab GUI - this article explains how...
3. Uitable sorting Matlab's uitables can be sortable using simple undocumented features...
4. Frameless (undecorated) figure windows Matlab figure windows can be made undecorated (borderless, title-less). ...

]]>
For the application that I will be presenting at next week’s MATLAB Expo in Munich (presentation slides), I wanted to add a text label at a specific location within the figure. The problem was, as you can clearly see from the screenshot below, that there is precious little available space for a new label. I could drive the entire content down to make space for it, but that would reduce the usable space for the actual contents, which is already at a premium:

Adding a transparent label to Matlab GUI (click for full-size image)

A natural place for the new label, as indicated, would be on top of the empty space next to the content’s sub-tabs (Correlation and Backtesting). This empty space is taken up by Matlab’s uitabgroup control, and we can simply place our label on top of it.

Well, easier said than done…

The obvious first attempt is to set the label’s position to [0,0,1,1] (in normalized units of its parent container). The label text will appear at the expected location, since Matlab labels are always top-aligned. However, the label’s opaque background will hide anything underneath (which is basically the entire content).

If we set the label’s position to something smaller (say, [.2,.9,.6,.1]), the label will now hide a much smaller portion of the content, but will still mask part of it (depending of the exact size of the figure) and for very small figure might actually make the label too small to display. Making the label background transparent will solve this dilemma.

Unfortunately, all Matlab controls are made opaque by default. Until recently there was not much that could be done about this, since all Matlab controls used heavyweight java.awt.Panel-derived containers that cannot be made transparent (details). Fortunately, in HG2 (R2014b onward) containers are now lightweight javax.swing.JPanel-derived and we can transform them and their contained control from opaque to non-opaque (i.e., having a transparent background).

There are 3 simple steps for this:

1. Find the text label control’s underlying Java peer (control) reference handle. This can be done using my findjobj utility, or by direct access via the containing uipanel hierarchy (if the label is inside such a uipanel), as explained here.
2. Set the Java label reference to be non-opaque (via its setOpaque() method)
3. Repaint the label via its repaint() method
% Create the Matlab text label uicontrol hLabel = uicontrol('Style','text', 'Parent',hPanel, 'Units','norm', 'Pos',[0,0,1,1], 'String','Results for BERY / PKG (1 hour)');   % Get the underlying Java peer (control) reference jLabel = findjobj(hLabel); %jLabel = hPanel.JavaFrame.getGUIDEView.getComponent(0).getComponent(0).getComponent(0).getComponent(0); % a direct alternative   % Set the control to be non-opaque and repaint it jLabel.setOpaque(false); jLabel.repaint();

This now looks nice, but not quite: Matlab displays the label text at the very top of its container, and this is not really in-line with the uitab labels. We need to add a small vertical padding at the top. One way to do this would be to set the label’s position to [0,0,1,.99] rather than [0,0,1,1]. Unfortunately, this results in varying amounts of padding depending on the container/figure height. A better alternative here would be to set the label to have a fixed-size padding amount. This can be done by attaching an empty Border to our JLabel:

% Attach a 6-pixel top padding jBorder = javax.swing.BorderFactory.createEmptyBorder(6,0,0,0); % top, left, bottom, right jLabel.setBorder(jBorder);

Another limitation is that while the transparent background presents the illusion of emptiness, trying to interact with any of the contents beneath it using mouse clicks fails because the mouse clicks are trapped by the Label background, transparent though it may be. We could reduce the label’s size so that it occludes a smaller portion of the content. Alternatively, we can remove the label’s mouse listeners so that any mouse events are passed-through to the controls underneath (i.e., not consumed by the label control, or actually it’s internal Java container):

jLabelParent = jLabel.getParent;   % Remove the mouse listeners from the control's internal container jListener = jLabelParent.getMouseListeners; jLabelParent.removeMouseListener(jListener(1));   jListener = jLabelParent.getMouseMotionListeners; jLabelParent.removeMouseMotionListener(jListener(1));

Using the label’s Java peer reference, we could do a lot of other neat stuff. A simple example for this is the VerticalAlignment or LineWrap properties – for some reason that eludes me, Matlab’s uicontrol only allows specifying the horizontal alignment and forces a line-wrap, despite the fact that these features are readily available in the underlying Java peer.

Finally, while it is not generally a good design practice to change fonts throughout the GUI, it sometimes makes sense to use different font colors, sizes, faces and/or attributes for parts of the label text, in various situations. For example, to emphasize certain things, as I’ve done in my title label. Such customizations can easily be done using HTML strings with most Matlab uicontrols, but unfortunately not for labels, even today in R2016a. MathWorks created custom code that removes the HTML support in Matlab labels, for reasons that elude me yet again, especially since Matlab upcoming future GUI will probably be web-based so it will also natively support HTML, so maybe there’s still hope that HTML will be supported in Matlab labels in a future release.

Anyway, the bottom line is that if we need our label to have HTML support today, we can use a standard Java JLabel and add it to the GUI using the javacomponent function. Here’s a simple usage example:

% Create the label and add it to the GUI jLabel = javaObjectEDT(javax.swing.JLabel('<html>Results for <b>BERY / PKG (1 Hour)</b></html>')); [hjLabel, hContainer] = javacomponent(jLabel, [10,10,10,10], hPanel); set(hContainer, 'Units','norm', 'Pos',[0,0,1,1])   % Make the label (and its internal container) transparent jLabel.getParent.getParent.setOpaque(false) % label's internal container jLabel.setOpaque(false) % the label control itself   % Align the label jLabel.setVerticalAlignment(jLabel.TOP); jLabel.setHorizontalAlignment(jLabel.CENTER);   % Add 6-pixel top border padding and repaint the label jLabel.setBorder(javax.swing.BorderFactory.createEmptyBorder(6,0,0,0)); jLabel.repaint;   % Now do the rest - mouse-listeners removal etc. ...

If you happen to attend the Matlab Expo next week in Munich Germany, please do come by and say hello!

]]>
https://undocumentedmatlab.com/blog/transparent-labels/feed 2
Smart listbox & editbox scrollbarshttps://undocumentedmatlab.com/blog/smart-listbox-editbox-scrollbars https://undocumentedmatlab.com/blog/smart-listbox-editbox-scrollbars#comments Wed, 20 Apr 2016 17:47:46 +0000 http://undocumentedmatlab.com/?p=6379

Related posts:
1. FindJObj GUI – display container hierarchy The FindJObj utility can be used to present a GUI that displays a Matlab container's internal Java components, properties and callbacks....
2. Editbox data input validation Undocumented features of Matlab editbox uicontrols enable immediate user-input data validation...
3. Customizing combobox popups Matlab combobox (dropdown) popups can be customized in a variety of ways. ...
4. Customizing editboxes Matlab's editbox can be customized in many useful manners...

]]>
A good friend recently asked me for examples where using Java in Matlab programs provides a significant benefit that would offset the risk of using undocumented/unsupported functionality, which may possibly stop working in some future Matlab release. Today I will discuss a very easy Java-based hack that in my opinion improves the appearance of Matlab GUIs with minimal risk of a catastrophic failure in a future release.

The problem with Matlab listbox and multi-line editbox controls in the current (non web-based) GUI, is that they use a scrollbar whose behavior policy is set to VERTICAL_SCROLLBAR_ALWAYS. This causes the vertical scrollbar to appear even when the listbox does not really require it. In many cases, when the listbox is too narrow, this also causes the automatic appearance of a horizontal scrollbar. The end result is a listbox that displays 2 useless scrollbars, that possibly hide some listbox contents, and are a sore to the eyes:

Standard (left) and smart (right) listbox scrollbars

default scrollbars (VERTICAL_SCROLLBAR_ALWAYS)

non-default scrollbars (VERTICAL_SCROLLBAR_AS_NEEDED)

By default, Matlab implements a vertical scrollbar policy of VERTICAL_SCROLLBAR_ALWAYS for sufficiently tall uicontrols (>20-25 pixels, which practically means always) and VERTICAL_SCROLLBAR_NEVER for shorter uicontrols (this may possibly be platform-dependent).

A similar problem happens with the horizontal scrollbar: Matlab implements a horizontal scrollbar policy of HORIZONTAL_SCROLLBAR_NEVER for all editboxes and also for narrow listboxes (<35 pixels), and HORIZONTAL_SCROLLBAR_AS_NEEDED for wide listboxes.

In many cases we may wish to modify the settings, as in the example shown above. The solution to this is very easy, as I explained back in 2010.

All we need to do is to retrieve the control’s underlying Java reference (a Java JScrollPane object) and change the policy value to VERTICAL_SCROLLBAR_AS_NEEDED:

% Create a multi-line (Max>1) editbox uicontrol hEditbox = uicontrol('style','edit', 'max',5, ...);   try % graceful-degradation for future compatibility % Get the Java scroll-pane container reference jScrollPane = findjobj(hEditbox);   % Modify the scroll-pane's scrollbar policies % (note the equivalent alternative methods used below) set(jScrollPane,'VerticalScrollBarPolicy',javax.swing.ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED); %VERTICAL_SCROLLBAR_AS_NEEDED=20 jScrollPane.setHorizontalScrollBarPolicy(javax.swing.ScrollPaneConstants.HORIZONTAL_SCROLLBAR_AS_NEEDED); %HORIZONTAL_SCROLLBAR_AS_NEEDED=30 catch % Never mind... end

Note that updating the uicontrol handle Position property has the side-effect of automatically reverting the scrollbar policies to their default values (HORIZONTAL_SCROLLBAR_NEVER and VERTICAL_SCROLLBAR_ALWAYS/NEVER). This also happens whenever the uicontrol is resized interactively (by resizing its container figure window, for example). It is therefore advisable to set jScrollPane’s ComponentResizedCallback property to “unrevert” the policies:

cbFunc = @(h,e) set(h,'VerticalScrollBarPolicy',20, 'HorizontalScrollBarPolicy',30); hjScrollPane = handle(jScrollPane,'CallbackProperties'); set(hjScrollPane,'ComponentResizedCallback',cbFunc);

### smart_scrollbars utility

I created a new utility called smart_scrollbars that implements all of this, which you can download from the Matlab File Exchange. The usage in Matlab code is very simple:

% Fix scrollbars for a specific listbox hListbox = uicontrol('style','list', ...); smart_scrollbars(hListbox)   % Fix scrollbars for a specific editbox hEditbox = uicontrol('style','edit', 'max',5, ...); smart_scrollbars(hEditbox)   % Fix all listbox/editbox scrollbars in a panel or figure smart_scrollbars % fixes all scrollbars in current figure (gcf) smart_scrollbars(hFig) % fixes all scrollbars in a specific figure smart_scrollbars(hContainer) % fixes all scrollbars in a container (panel/tab/...)

### Performance considerations

Finding the underlying JScrollPane reference of Matlab listboxes/editboxes can take some time. While the latest version of findjobj significantly improved the performance of this, it can still take quite a while in complex GUIs. For this reason, it is highly advisable to limit the search to a Java container of the control that includes as few internal components as possible.

In R2014b or newer, this is easily achieved by wrapping the listbox/editbox control in a tightly-fitting invisible uipanel. The reason is that in R2014b, uipanels have finally become full-fledged Java components (which they weren’t until then), but more to the point they now contain a property with a direct reference to the underlying JPanel. By using this panel reference we limit findjobj‘s search only to the contained scrollpane, and this is much faster:

% Slower code: hListbox = uicontrol('style','list', 'parent',hParent, 'pos',...); smart_scrollbars(hListbox)   % Much faster (using a tightly-fitting transparent uipanel wrapper): hPanel = uipanel('BorderType','none', 'parent',hParent, 'pos',...); % same position/units/parent as above hListbox = uicontrol('style','list', 'parent',hPanel, 'units','norm', 'pos',[0,0,1,1], ...); smart_scrollbars(hListbox)

The smart_scrollbars utility detects cases where there is a potential for such speedups and reports it in a console warning message:

>> smart_scrollbars(hListbox) Warning: smart_scrollbars can be much faster if the list/edit control is wrapped in a tightly-fitting uipanel (details)

If you wish, you can suppress this warning using code such as the following:

oldWarn = warning('off', 'YMA:smart_scrollbars:uipanel'); smart_scrollbars(hListbox) warning(oldWarn); % restore warnings

### Musings on future compatibility

Going back to my friend’s question at the top of today’s post, the risk of future compatibility was highlighted in the recent release of Matlab R2016a, which introduced web-based uifigures and controls, for which the vast majority of Java hacks that I presented in this blog since 2009 (including today’s hack) will not work. While the full transition from Java-based to web-based GUIs is not expected anytime soon, this recent addition highlighted the risk inherent in using unsupported functionality.

Users can take a case-by-case decision whether any improved functionality or appearance using Java hacks is worth the extra risk: On one hand, such hacks have been quite stable and worked remarkably well for the past decade, and will probably continue working into 2020 or so (or longer if you keep using a not up-to-the-moment Matlab release, or if you create compiled applications). On the other hand, once they stop working sometime in R2020a (or whenever), major code rewrites may possibly be required, depending on the amount of dependency of your code on these hacks.

There is an obvious tradeoff between improved GUIs now and for the coming years, versus increased maintainability cost a few years in the future. Each specific GUI will have its own sweet spot on the wide spectrum between using no such hacks at all, through non-critical hacks that provide graceful functionality degradation if they ever fail, to major Java-based functionality that would require complete rework. It is certainly NOT an all-or-nothing decision. Users who take the conservative approach of using no unsupported feature at all, lose the opportunity to have professional grade Matlab GUIs today and in the upcoming years. Decisions, decisions, …

In any case, we can reduce the risk of using such hacks today by carefully wrapping all their code in try-catch blocks. This way, even if the code fails in some future Matlab release, we’d still be left with a working implementation based on fully-supported functionality. This is the reason why I’ve used such a block in the code snippet above, as well as in my smart_scrollbars utility. What this means is that you can safely use smart_scrollbars in your code today and if the worst happens and it stops working in a few years, then it will simply do nothing without causing any error. In other word, future compatibility in the form of graceful degradation. I strongly advise using such defensive coding techniques whenever you use unsupported features.

]]>
https://undocumentedmatlab.com/blog/smart-listbox-editbox-scrollbars/feed 6
Faster findjobjhttps://undocumentedmatlab.com/blog/faster-findjobj https://undocumentedmatlab.com/blog/faster-findjobj#comments Mon, 11 Apr 2016 09:18:14 +0000 http://undocumentedmatlab.com/?p=6376

Related posts:
1. FindJObj – find a Matlab component’s underlying Java object The FindJObj utility can be used to access and display the internal components of Matlab controls and containers. This article explains its uses and inner mechanism....
2. FindJObj GUI – display container hierarchy The FindJObj utility can be used to present a GUI that displays a Matlab container's internal Java components, properties and callbacks....
3. Customizing Matlab labels Matlab's text uicontrol is not very customizable, and does not support HTML or Tex formatting. This article shows how to display HTML labels in Matlab and some undocumented customizations...
4. Continuous slider callback Matlab slider uicontrols do not enable a continuous-motion callback by default. This article explains how this can be achieved using undocumented features....

]]>
My findjobj utility, created in 2007 and updated over the years, has received wide recognition and is employed by numerous Matlab programs, including a few dozen utilities in the Matlab File Exchange. I am quite proud of this utility and find it extremely useful for customizing Matlab controls in many ways that are impossible using standard Matlab properties. I have shown many examples of this in this blog over the past years.

I am happy to announce that I have just uploaded a new version of findjobj to the Matlab File Exchange, which significantly improves the utility’s performance for the most common use-case of a single input and a single output, namely finding the handle of the underlying Java component (peer) of a certain Matlab control:

>> hButton = uicontrol('String','click me!');   >> tic, jButton = findjobj(hButton); toc % old findjobj Elapsed time is 1.513217 seconds.   >> tic, jButton = findjobj(hButton); toc % new findjobj Elapsed time is 0.029348 seconds.

The new findjobj is backward-compatible with the old findjobj and with all prior Matlab releases. It is a drop-in replacement that will significantly improve your program’s speed.

The new version relies on several techniques:

First, as I showed last year, in HG2 (R2014 onward), Matlab uipanels have finally become full-featured Java JPanels, that can be accessed and customized in many interesting manners. More to the point here, we can now directly access the underlying JPanel component handle using the uipanel‘s hidden JavaFrame property (thanks to MathWorks for supplying this useful hook!). The new findjobj version detects this and immediately returns this handle if the user specified a uipanel input.

I still do not know of any direct way to retrieve the underlying Java component’s handle for Matlab uicontrols, this has been a major frustration of mine for quite a few years. So, we need to find the containing Java container in which we will recursively search for the control’s underlying Java handle. In the old version of finjobj, we retrieve the containing figure’s JFrame reference and from it the ContentPane handle, and use this handle as the Java container that is recursively searched. This is quite slow when the figure window is heavily-laden with multiple controls. In the new version, we try to use the specified Matlab uicontrol‘s direct parent, which is very often a uipanel. In this case, we can directly retrieve the panel’s JPanel reference as explained above. This results in a must smaller and faster search since we need to recursively search far fewer controls within the container, compared to the figure’s ContentPane.

In addition, I used a suggestion by blog reader Hannes for a faster recursive search that uses the control’s tooltip rather than its size, position and class. Finally, the search order is reversed to search backward from the last child component, since this is the component that will most often contain the requested control peer.

Feel free to download and use the new findjobj version. The code for the fast variant can be found in lines #190-205 and #3375-3415.

Enjoy!

p.s. – as I explained last week, today’s discussion, and in general anything that has to do with Java peers of GUI controls, only relates to the existing JFrame-based figure windows, not to the new web-based uifigure.

]]>
https://undocumentedmatlab.com/blog/faster-findjobj/feed 11
Adding a search box to figure toolbarhttps://undocumentedmatlab.com/blog/adding-a-search-box-to-figure-toolbar https://undocumentedmatlab.com/blog/adding-a-search-box-to-figure-toolbar#comments Wed, 30 Mar 2016 13:50:53 +0000 http://undocumentedmatlab.com/?p=6353

Related posts:
1. Enable/disable entire figure window Disabling/enabling an entire figure window is impossible with pure Matlab, but is very simple using the underlying Java. This article explains how....
2. Setting status-bar text The Matlab desktop and figure windows have a usable statusbar which can only be set using undocumented methods. This post shows how to set the status-bar text....
3. Figure toolbar components Matlab's toolbars can be customized using a combination of undocumented Matlab and Java hacks. This article describes how to access existing toolbar icons and how to add non-button toolbar components....
4. Figure toolbar customizations Matlab's toolbars can be customized using a combination of undocumented Matlab and Java hacks. This article describes how to customize the Matlab figure toolbar....

]]>
Last week I wrote about my upcoming presentations in Tel Aviv and Munich, where I will discuss a Matlab-based financial application that uses some advanced GUI concepts. In today’s post I will review one of these concepts that could be useful in a wide range of Matlab applications – adding an interactive search box to the toolbar of Matlab figures.

The basic idea is simple: whenever the user types in the search box, a Matlab callback function checks the data for the search term. If one or more matches are found then the searchbox’s background remains white, otherwise it is colored yellow to highlight the term. When the user presses <Enter>, the search action is triggered to highlight the term in the data, and any subsequent press of <Enter> will highlight the next match (cycling back at the top as needed). Very simple and intuitive:

Interactive search-box in Matlab figure toolbar

In my specific case, the search action (highlighting the search term in the data) involved doing a lot of work: updating multiple charts and synchronizing row selection in several connected uitables. For this reason, I chose not to do this action interactively (upon each keypress in the search box) but rather only upon clicking <Enter>. In your implementation, if the search action is simpler and faster, you could do it interactively for an even more intuitive effect.

### Technical components

The pieces of today’s post were already discussed separately on this website, but never shown together as I will do today:

### Adding a search-box to the figure toolbar

As a first step, let’s create the search-box component and add it to our figure’s toolbar:

### Custom controls

As I explained in last week’s post, we can use scUtils.addShortcutToBottom to add a simple push-button shortcut to the relevant category panel within the Shortcuts toolstrip tab. To add custom controls, we can simply add the controls to the relevant shortcut category panel container (a com.mathworks.toolstrip.components.TSPanel object). The standard shortcuts are typically placed in the Shortcuts tab’s second TSPanel (“general”), and other categories have TSPanels of their own.

Now here’s the tricky part about TSPanels: we cannot directly add components to the sectino panel (that would be too easy…): the section panels are composed of an array of internal TSPanels, and we need to add the new controls to those internal panels. However, these panels only contain 3 empty slots. If we try to add more than 3 components, the 4th+ component(s) will simply not be displayed. In such cases, we need to create a new TSPanel to display the extra components.

Here then is some sample code to add a combo-box (drop-down) control:

% First, get the last internal TSPanel within the Shortcuts tab's "general" section panel % Note: jToolstrip was defined in the previous section above jShortcutsTab = jToolstrip.getModel.get('shortcuts').getComponent; jSectionPanel = jShortcutsTab.getSectionComponent(1).getSection.getComponent; % the TSPanel object "general" jContainer = jSectionPanel.getComponent(jSectionPanel.getComponentCount-1);   % If the last internal TSPanel is full, then prepare a new internal TSPanel next to it if jContainer.getComponentCount >= 3 % Create a new empty TSPanel and add it to the right of the last internal TSPanel jContainer = com.mathworks.toolstrip.components.TSPanel; jContainer.setPreferredSize(java.awt.Dimension(100,72)); jSectionPanel.add(jContainer); jSectionPanel.repaint(); jSectionPanel.revalidate(); end   % Create the new control with a custom tooltip and callback function optionStrings = {'Project A', 'Project B', 'Project C'}; jCombo = com.mathworks.toolstrip.components.TSComboBox(optionStrings); jCombo = handle(javaObjectEDT(jCombo), 'callbackproperties')); set(jCombo, 'ActionPerformedCallback', @myCallbackFunction); jCombo.setToolTipText('Select the requested project');   % Now add the new control to the internal TSPanel jContainer.add(jCombo); jContainer.repaint(); jContainer.revalidate();

Custom shortcut controls

Matlab’s internal com.mathworks.toolstrip.components package contains many embeddable controls, including the following (I emphasized those that I think are most useful within the context of the Shortcuts panel): TSButton, TSCheckBox, TSComboBox, TSDropDownButton (a custom combo-box component), TSFormattedTextField, TSLabel, TSList, TSRadioButton, TSScrollPane, TSSlider, TSSpinner, TSSplitButton, TSTextArea, TSTextField, and TSToggleButton. These controls are in most cases simple wrappers of the corresponding Java Swing controls. For example, TSSpinner extends the standard Swing JSpinner control. In some cases, the controls are more complex: for example, the TSSplitButton is similar to Matlab’s uisplittool control.

Toolstrip controls

In fact, these controls can be used even outside the toolstrip, embedded directly in our Matlab figure GUI, using the javacomponent function. For example:

dataModel = javax.swing.SpinnerNumberModel(125, 15, 225, 0.5); % defaultValue, minValue, maxValue, stepSize jSpinner = com.mathworks.toolstrip.components.TSSpinner(dataModel); jSpinner = handle(javaObjectEDT(jSpinner), 'CallbackProperties'); [hjSpinner, hContainer] = javacomponent(jSpinner, [10,10,60,20], gcf);

You can find additional interesting components within the %matlabroot%/java/jar/toolstrip.jar file, which can be opened in any zip file utility or Java IDE. In fact, whatever controls that you see Matlab uses in its Desktop toolstrip (including galleries etc.) can be replicated in custom tabs, sections and panels of our own design.

Matlab Desktop’s interactive GUI only enables creating simple push-button shortcuts having string callbacks (that are eval‘ed in run-time). Using the undocumented programmatic interface that I just showed, we can include more sophisticated controls, as well as customize those controls in ways that are impossible via the programmatic GUI: add tooltips, set non-string (function-handle) callbacks, enable/disable controls, modify icons in run-time etc.

For example (intentionally showing two separate ways of setting the component properties):

% Toggle-button jTB = handle(javaObjectEDT(com.mathworks.toolstrip.components.TSToggleButton('Toggle button')), 'CallbackProperties') jTB.setSelected(true) jTB.setToolTipText('toggle me!') jTB.ActionPerformedCallback = @(h,e)doSomething(); jContainer.add(jTB);   % Check-box jCB = handle(javaObjectEDT(com.mathworks.toolstrip.components.TSCheckBox('selected !')), 'CallbackProperties'); set(jCB, 'Selected', true, 'ToolTipText','Please select me!', 'ActionPerformedCallback',{@myCallbackFunction,extraData}); jContainer.add(jCB);

(resulting in the screenshot at the top of this post)

Important note: none of these customizations is saved to file. Therefore, they need to be redone programmatically for each separate Matlab session. You can easily do that by calling the relevant code in your startup.m file.

If you wish me to assist with any customization of the Desktop shortcuts, or any other Matlab aspect, then contact me for a short consultancy.

Happy New Year everybody!

]]>
https://undocumentedmatlab.com/blog/programmatic-shortcuts-manipulation-part-2/feed 4