Undocumented Matlab
  • SERVICES
    • Consulting
    • Development
    • Training
    • Gallery
    • Testimonials
  • PRODUCTS
    • IQML: IQFeed-Matlab connector
    • IB-Matlab: InteractiveBrokers-Matlab connector
    • EODML: EODHistoricalData-Matlab connector
    • Webinars
  • BOOKS
    • Secrets of MATLAB-Java Programming
    • Accelerating MATLAB Performance
    • MATLAB Succinctly
  • ARTICLES
  • ABOUT
    • Policies
  • CONTACT
  • SERVICES
    • Consulting
    • Development
    • Training
    • Gallery
    • Testimonials
  • PRODUCTS
    • IQML: IQFeed-Matlab connector
    • IB-Matlab: InteractiveBrokers-Matlab connector
    • EODML: EODHistoricalData-Matlab connector
    • Webinars
  • BOOKS
    • Secrets of MATLAB-Java Programming
    • Accelerating MATLAB Performance
    • MATLAB Succinctly
  • ARTICLES
  • ABOUT
    • Policies
  • CONTACT

Multi-column (grid) legend

February 7, 2011 5 Comments

I would like to welcome guest blogger Adrian Cherry. Adrian will describe a very handy utility that shows how basic built-in Matlab functions can be improved and customized by just a bit of fiddling under Matlab’s hood.

Legend Plotting

Whilst I enjoy using the many time saving features of Matlab, one area where I feel it suffers is the technical plotting and annotation. This tale relates the development of a legend plotting routine, gridLegend, in an effort to improve the presentation.
In my day job we have a requirement to condense a large quantity of data onto summary charts. However, there is only so much data consolidation possible before you start losing the information required. We often need to plot 40 or 50 lines of test data to visualize trends or outliers, using the legend to identify the number of test hours against each test specimen.
Using the standard Matlab legend function resulted in a long legend over twice the size of the associated plot:

Standard Matlab legend
Standard Matlab legend

I wanted some way of generating a more compact legend format.
Fortunately earlier in the year, an entry on Matlab Central allowing a multi-column legend to be generated was posted, columnlegend. Although lacking some features, columnlegend gave me a good start on developing what I wanted for a multi column legend, culminating in gridLegend:
Multi-column legend
Multi-column legend

Delving into the Undocumented Matlab

So where is the link with undocumented Matlab?
As mentioned in the original columnlegend entry, it was relatively simple to redraw the legend as required on the screen. However, as soon as the figure was printed or exported to an image file, internal Matlab workings would redraw the figure, including the legend, thereby undoing my careful legend crafting, squeezing it back into one column (Yuck!):

Matlab-reverted multi-column legend
Matlab-reverted multi-column legend

As we wanted to automatically output images files, I had to delve into the hidden areas of Matlab to try to solve this problem.
My initial thought was to find out where the figure got redrawn for printing or export and override the standard legend call with a call to my new function. I couldn’t find the obvious culprit, stepping as far as I could through the print function there didn’t appear to be any call to the legend function.
In my search for information on how the legend worked I found the undocumented Matlab article about generating dynamic legends. This dynamic-legend post covered details about attaching a listener to a child of the legend axes, in Matlab the legend function creates its own set of axes on the figure to display the legend.
Armed with the information that legend axes objects could have listeners attached, I considered that these might be the source of redrawing the legend for printing. So with the legend I had generated I took a look at what listeners were attached, using the undocumented hidden axes property ScribeLegendListeners:

>> legendListener = get(gca,'ScribeLegendListeners')
legendListener =
        fontname: [1x1 handle.listener]
        fontsize: [1x1 handle.listener]
      fontweight: [1x1 handle.listener]
       fontangle: [1x1 handle.listener]
       linewidth: [1x1 handle.listener]
         deleted: [1x1 handle.listener]
    proxydeleted: [1x1 handle.listener]

>> legendListener = get(gca,'ScribeLegendListeners') legendListener = fontname: [1x1 handle.listener] fontsize: [1x1 handle.listener] fontweight: [1x1 handle.listener] fontangle: [1x1 handle.listener] linewidth: [1x1 handle.listener] deleted: [1x1 handle.listener] proxydeleted: [1x1 handle.listener]

The font size and line positioning were all being redrawn for printing so this was potentially the source of my problem. However I’d not looked at a handle.listener before, so a little further digging was required:

K>> get(legendListener.fontname)
      SourceObject: [1x1 schema.prop]
         Container: [1x1 axes]
         EventType: 'PropertyPostSet'
          Callback: {2x1 cell}
    CallbackTarget: []
           Enabled: 'on'

K>> get(legendListener.fontname) SourceObject: [1x1 schema.prop] Container: [1x1 axes] EventType: 'PropertyPostSet' Callback: {2x1 cell} CallbackTarget: [] Enabled: 'on'

The option Enabled immediately drew my attention, and so the following lines were added to my gridLegend function to switch off these listeners and apply it back to the legend:

LL = get(gca,'ScribeLegendListeners');
set(LL.fontname,'enabled','off');
set(LL.fontsize,'enabled','off');
set(LL.fontweight,'enabled','off');
set(LL.fontangle,'enabled','off');
set(LL.linewidth,'enabled','off');
set(gca,'ScribeLegendListeners',LL);

LL = get(gca,'ScribeLegendListeners'); set(LL.fontname,'enabled','off'); set(LL.fontsize,'enabled','off'); set(LL.fontweight,'enabled','off'); set(LL.fontangle,'enabled','off'); set(LL.linewidth,'enabled','off'); set(gca,'ScribeLegendListeners',LL);

Finally allowing me to output the image files with a multi-column legend:

Printed multi-column legend
Printed multi-column legend

So my thanks to the contributors on Matlab Central who enabled me to get started on gridLegend and to Yair for collating the many nuggets of information on Undocumented Matlab which allowed me to complete the function and get it posted on Matlab Central.
Multi-column legend in action
Multi-column legend in action

Related posts:

  1. Multi-line uitable column headers – Matlab uitables can present long column headers in multiple lines, for improved readability. ...
  2. Transparent legend – Matlab chart legends are opaque be default but can be made semi- or fully transparent. ...
  3. Plot legend customization – Matlab plot legends and their internal components can be customized using a variety of undocumented properties that are easily accessible. ...
  4. Plot legend title – Titles to plot legends are easy to achieve in HG1 (R2014a or earlier), but much more difficult in HG2 (R2014b or newer). ...
  5. 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....
  6. Multi-line tooltips – Multi-line tooltips are very easy to set up, once you know your way around a few undocumented hiccups....
Adrian Cherry Handle graphics Hidden property Listener Pure Matlab scribe Undocumented feature Undocumented property
Print Print
« Previous
Next »
5 Responses
  1. toto March 13, 2011 at 20:26 Reply

    thank you about this. Now I can create legend modified with Matlab. Nice tutorial.

  2. Michelle May 17, 2012 at 14:29 Reply

    Thank you!!

  3. Dora December 25, 2014 at 18:56 Reply

    That’s exactly what I’m looking for, thanks so much!

  4. Dan March 28, 2016 at 21:50 Reply

    I’m working with a bit of code that works on my boss’ computer but doesn’t work on mine. I have 2015b, I believe he has a 2013 version. When I try

    LL = get(gca,'ScribeLegendListeners');

    LL = get(gca,'ScribeLegendListeners');

    I get an error saying “There is no ScribeLegendListeners property on the Axes class.” Is this because something changed in the 2015 release?

    • Yair Altman March 29, 2016 at 03:33 Reply

      @Dan – In R2014b Matlab’s graphics engine has been completely revamped (a.k.a. “HG2”, for “Handle Graphics version 2”). This is one of the many fallouts. If you dig inside the utility’s code, you may find a way to modify it to work on HG2. Or you can contact Adrian to ask him to do this.

Leave a Reply
HTML tags such as <b> or <i> are accepted.
Wrap code fragments inside <pre lang="matlab"> tags, like this:
<pre lang="matlab">
a = magic(3);
disp(sum(a))
</pre>
I reserve the right to edit/delete comments (read the site policies).
Not all comments will be answered. You can always email me (altmany at gmail) for private consulting.

Click here to cancel reply.

Useful links
  •  Email Yair Altman
  •  Subscribe to new posts (feed)
  •  Subscribe to new posts (reader)
  •  Subscribe to comments (feed)
 
Accelerating MATLAB Performance book
Recent Posts

Speeding-up builtin Matlab functions – part 3

Improving graphics interactivity

Interesting Matlab puzzle – analysis

Interesting Matlab puzzle

Undocumented plot marker types

Matlab toolstrip – part 9 (popup figures)

Matlab toolstrip – part 8 (galleries)

Matlab toolstrip – part 7 (selection controls)

Matlab toolstrip – part 6 (complex controls)

Matlab toolstrip – part 5 (icons)

Matlab toolstrip – part 4 (control customization)

Reverting axes controls in figure toolbar

Matlab toolstrip – part 3 (basic customization)

Matlab toolstrip – part 2 (ToolGroup App)

Matlab toolstrip – part 1

Categories
  • Desktop (45)
  • Figure window (59)
  • Guest bloggers (65)
  • GUI (165)
  • Handle graphics (84)
  • Hidden property (42)
  • Icons (15)
  • Java (174)
  • Listeners (22)
  • Memory (16)
  • Mex (13)
  • Presumed future risk (394)
    • High risk of breaking in future versions (100)
    • Low risk of breaking in future versions (160)
    • Medium risk of breaking in future versions (136)
  • Public presentation (6)
  • Semi-documented feature (10)
  • Semi-documented function (35)
  • Stock Matlab function (140)
  • Toolbox (10)
  • UI controls (52)
  • Uncategorized (13)
  • Undocumented feature (217)
  • Undocumented function (37)
Tags
ActiveX (6) AppDesigner (9) Callbacks (31) Compiler (10) Desktop (38) Donn Shull (10) Editor (8) Figure (19) FindJObj (27) GUI (141) GUIDE (8) Handle graphics (78) HG2 (34) Hidden property (51) HTML (26) Icons (9) Internal component (39) Java (178) JavaFrame (20) JIDE (19) JMI (8) Listener (17) Malcolm Lidierth (8) MCOS (11) Memory (13) Menubar (9) Mex (14) Optical illusion (11) Performance (78) Profiler (9) Pure Matlab (187) schema (7) schema.class (8) schema.prop (18) Semi-documented feature (6) Semi-documented function (33) Toolbar (14) Toolstrip (13) uicontrol (37) uifigure (8) UIInspect (12) uitools (20) Undocumented feature (187) Undocumented function (37) Undocumented property (20)
Recent Comments
  • Nicholas (6 days 13 hours ago): Hi Yair, Thanks for the reply. I am on Windows 10. I also forgot to mention that this all works wonderfully out of the editor. It only fails once compiled. So, yes, I have tried a...
  • Nicholas (6 days 13 hours ago): Hi Yair, Thanks for the reply. I am on Windows 10. I also forgot to mention that this all works wonderfully out of the editor. It only fails once compiled. So, yes, I have tried a...
  • Yair Altman (6 days 20 hours ago): Nicholas – yes, I used it in a compiled Windows app using R2022b (no update). You didn’t specify the Matlab code location that threw the error so I can’t help...
  • Nicholas (7 days 17 hours ago): Hi Yair, Have you attempted your displayWebPage utility (or the LightweightHelpPanel in general) within a compiled application? It appears to fail in apps derived from both R2022b...
  • João Neves (10 days 21 hours ago): I am on matlab 2021a, this still works: url = struct(struct(struct(struct(hF ig).Controller).PlatformHost). CEF).URL; but the html document is empty. Is there still a way to do...
  • Yair Altman (13 days 20 hours ago): Perhaps the class() function could assist you. Or maybe just wrap different access methods in a try-catch so that if one method fails you could access the data using another...
  • Jeroen Boschma (13 days 22 hours ago): Never mind, the new UI components have an HTML panel available. Works for me…
  • Alexandre (13 days 23 hours ago): Hi, Is there a way to test if data dictionnatry entry are signal, simulink parameters, variables … I need to access their value, but the access method depends on the data...
  • Nicholas (14 days 14 hours ago): In case anyone is looking for more info on the toolbar: I ran into some problems creating a toolbar with the lightweight panel. Previously, the Browser Panel had an addToolbar...
  • Jeroen Boschma (17 days 21 hours ago): I do not seem to get the scrollbars (horizontal…) working in Matlab 2020b. Snippets of init-code (all based on Yair’s snippets on this site) handles.text_explorer...
  • Yair Altman (45 days 23 hours ago): m_map is a mapping tool, not even created by MathWorks and not part of the basic Matlab system. I have no idea why you think that the customizations to the builtin bar function...
  • chengji chen (46 days 5 hours ago): Hi, I have tried the method, but it didn’t work. I plot figure by m_map toolbox, the xticklabel will add to the yticklabel at the left-down corner, so I want to move down...
  • Yair Altman (53 days 22 hours ago): @Alexander – this is correct. Matlab stopped including sqlite4java in R2021b (it was still included in 21a). You can download the open-source sqlite4java project from...
  • Alexander Eder (59 days 18 hours ago): Unfortunately Matlab stopped shipping sqlite4java starting with R2021(b?)
  • K (66 days 5 hours ago): Is there a way to programmatically manage which figure gets placed where? Let’s say I have 5 figures docked, and I split it into 2 x 1, I want to place 3 specific figures on the...
Contact us
Captcha image for Custom Contact Forms plugin. You must type the numbers shown in the image
Undocumented Matlab © 2009 - Yair Altman
This website and Octahedron Ltd. are not affiliated with The MathWorks Inc.; MATLAB® is a registered trademark of The MathWorks Inc.
Scroll to top