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

Editbox data input validation

October 2, 2013 7 Comments

Last week I explained how Matlab’s editbox control can be customized using its underlying Java component. Today I extend that article by explaining how we can use this information to provide a very user-friendly input-validation function for Matlab editboxes.

Zip-code entry validation example
Zip-code entry validation example


As before, we first need to get the Matlab control’s underlying Java control. This is done using the findjobj utility:

% Prepare the log editbox
hEditbox = uicontrol('Style','edit', 'String','Matlab', ...);
% Get the underlying Java editbox
jEditbox = findjobj(hLogPanel);
try
    % Multi-line editboxes are contained within a scroll-panel
    jEditbox = handle(jEditbox.getViewport.getView, 'CallbackProperties');
catch
    % probably a single-line editbox
end

% Prepare the log editbox hEditbox = uicontrol('Style','edit', 'String','Matlab', ...); % Get the underlying Java editbox jEditbox = findjobj(hLogPanel); try % Multi-line editboxes are contained within a scroll-panel jEditbox = handle(jEditbox.getViewport.getView, 'CallbackProperties'); catch % probably a single-line editbox end

Callbacks

Once we have the jEditbox reference handle, we can use some ~30 different event callbacks that it exposes. Some of the useful callbacks include:

  • ActionPerformedCallback – fired when <enter> is clicked in the editbox
  • CaretUpdateCallback – fired when the caret position has changed
  • KeyTypedCallback – fired whenever a keyboard button is typed when the editbox has focus

For example:

set(jEditbox, 'KeyPressedCallback',@myValidationFunction);
% Callback function definition
function myValidationFunction(jEditbox, eventData)
    % The following comments refer to the case of Alt-Shift-b
    keyChar = get(eventData,'KeyChar');  % or: eventData.getKeyChar  ==> 'B'
    isAltDown = get(eventData,'AltDown');  % ==> 'on'
    isAltDown = eventData.isAltDown;  % ==> true
    modifiers = get(eventData,'Modifiers');  % or: eventData.getModifiers ==> 9 = 1 (Shift) + 8 (Alt)
    modifiersDescription = char(eventData.getKeyModifiersText(modifiers));  % ==> 'Alt+Shift'
    % (now decide what to do with this key-press...)
end

set(jEditbox, 'KeyPressedCallback',@myValidationFunction); % Callback function definition function myValidationFunction(jEditbox, eventData) % The following comments refer to the case of Alt-Shift-b keyChar = get(eventData,'KeyChar'); % or: eventData.getKeyChar ==> 'B' isAltDown = get(eventData,'AltDown'); % ==> 'on' isAltDown = eventData.isAltDown; % ==> true modifiers = get(eventData,'Modifiers'); % or: eventData.getModifiers ==> 9 = 1 (Shift) + 8 (Alt) modifiersDescription = char(eventData.getKeyModifiersText(modifiers)); % ==> 'Alt+Shift' % (now decide what to do with this key-press...) end

Using such a validation function enables us to immediately convert typed characters into ‘*’ (in password fields) or check that the input conforms to a standard format such as a 5-digit zip code, a valid-looking email address or a valid-looking credit-card number (Luhn’s algorithm, recently featured in a video tutorial by Doug Hull). Of course, there are dedicated JIDE controls that do much of this already, but let’s not digress.
In today’s example, we shall implement a simple input-validation function for a 5-digit zip code. When the input data is invalid, the editbox will be colored red and an appropriate message will appear next to the editbox. In addition, invalid (non-digit) characters shall be rejected with a beep sound.

Zip-code validation example

To illustrate the above, let’s use an example of a 5-digit zip-code entry validation. We start by creating an empty editbox with an associated message label next to it:

figure('Color','w', 'Menubar','none');
hEditbox = uicontrol('Style','edit', 'Pos',[10,10,60,20], 'String','Matlab');  % start with an invalid string
hMessageLabel = uicontrol('Style','text', 'Pos',[80,10,200,20], 'horizontal','left', 'background','w', 'Foreground','red');

figure('Color','w', 'Menubar','none'); hEditbox = uicontrol('Style','edit', 'Pos',[10,10,60,20], 'String','Matlab'); % start with an invalid string hMessageLabel = uicontrol('Style','text', 'Pos',[80,10,200,20], 'horizontal','left', 'background','w', 'Foreground','red');

Next we get the underlying jEditbox reference and set its entry-validation callback function:

jEditbox = findjobj(hEditbox);  % single-line editbox so there's need to drill-down the scroll-pane
set(jEditbox, 'KeyPressedCallback',{@editboxValidation,hMessageLabel});

jEditbox = findjobj(hEditbox); % single-line editbox so there's need to drill-down the scroll-pane set(jEditbox, 'KeyPressedCallback',{@editboxValidation,hMessageLabel});

Note how we pass the message-label’s handle as an extra input parameter to the callback function.
Now we define the callback function editboxValidation and place it on the Matlab path (for example, by placing the following within editboxValidation.m in a folder that is already on your path):

% editboxValidation - ensure that an editbox input is a valid 5-digit zip code
function editboxValidation(jEditbox, eventData, hMessageLabel)
    keyChar = eventData.getKeyChar;  % see note below about how we can trick Matlab here
    if ~alldigits(keyChar) && isprintable(keyChar)
        beep;
        fixedText = strrep(char(jEditbox.getText), keyChar, '');
        jEditbox.setText(fixedText);
    end
    updateAppearance(jEditbox, hMessageLabel);
end
% Check whether a string only contains digits
function flag = alldigits(str)
    flag = ~isnan(str2double(str));
end
% Check whether a character is printable
function flag = isprintable(keyChar)
    keyVal = double(keyChar);
    flag = ~isempty(keyVal) && keyVal > 31 && keyVal < 128;
end
% Update the GUI appearance based on the editbox text
function updateAppearance(jEditbox, hMessageLabel)
    currentText = char(jEditbox.getText);
    if isempty(currentText)
        set(hMessageLabel, 'String','Please enter a 5-digit zip-code')
        jEditbox.setBorder(javax.swing.border.LineBorder(java.awt.Color.red, 3, false));
    elseif ~alldigits(currentText)
        beep;
        set(hMessageLabel, 'String','Invalid zip: should only contain digits')
        jEditbox.setBorder(javax.swing.border.LineBorder(java.awt.Color.red, 3, false));
    elseif length(currentText) ~= 5
        set(hMessageLabel, 'String','Invalid zip: should have exactly 5 digits')
        jEditbox.setBorder(javax.swing.border.LineBorder(java.awt.Color.red, 3, false));
    else
        set(hMessageLabel, 'String','');
        jEditbox.setBorder(javax.swing.border.LineBorder(java.awt.Color.gray, 1, false));
    end
end

% editboxValidation - ensure that an editbox input is a valid 5-digit zip code function editboxValidation(jEditbox, eventData, hMessageLabel) keyChar = eventData.getKeyChar; % see note below about how we can trick Matlab here if ~alldigits(keyChar) && isprintable(keyChar) beep; fixedText = strrep(char(jEditbox.getText), keyChar, ''); jEditbox.setText(fixedText); end updateAppearance(jEditbox, hMessageLabel); end % Check whether a string only contains digits function flag = alldigits(str) flag = ~isnan(str2double(str)); end % Check whether a character is printable function flag = isprintable(keyChar) keyVal = double(keyChar); flag = ~isempty(keyVal) && keyVal > 31 && keyVal < 128; end % Update the GUI appearance based on the editbox text function updateAppearance(jEditbox, hMessageLabel) currentText = char(jEditbox.getText); if isempty(currentText) set(hMessageLabel, 'String','Please enter a 5-digit zip-code') jEditbox.setBorder(javax.swing.border.LineBorder(java.awt.Color.red, 3, false)); elseif ~alldigits(currentText) beep; set(hMessageLabel, 'String','Invalid zip: should only contain digits') jEditbox.setBorder(javax.swing.border.LineBorder(java.awt.Color.red, 3, false)); elseif length(currentText) ~= 5 set(hMessageLabel, 'String','Invalid zip: should have exactly 5 digits') jEditbox.setBorder(javax.swing.border.LineBorder(java.awt.Color.red, 3, false)); else set(hMessageLabel, 'String',''); jEditbox.setBorder(javax.swing.border.LineBorder(java.awt.Color.gray, 1, false)); end end

Finally, we call the validation function directly after creating our GUI, to let the user know that the zip-code needs to be entered:

% Note how we trick Matlab by using eventData as a struct rather than a Java object
% (i.e., getKeyChar is set here to be a simple struct field, rather than a Java method)
eventData.getKeyChar = '';
editboxValidation(jEditbox,eventData,hMessageLabel)

% Note how we trick Matlab by using eventData as a struct rather than a Java object % (i.e., getKeyChar is set here to be a simple struct field, rather than a Java method) eventData.getKeyChar = ''; editboxValidation(jEditbox,eventData,hMessageLabel)

Zip-code entry validation example
Zip-code entry validation example

Naturally, this is a very simple example, and you can easily expand it for your needs. But it does show the basic components of any input validation: checking the new data, updating the control as appropriate, and modifying the appearance of the underlying control and of other associated controls.

Available report – “Advanced Customizations of Matlab Uicontrols”

Interested readers can find more information about these and other possible customizations in my report on “Advanced Customizations of Matlab Uicontrols“. This 90-page PDF report can be purchased here ($29, please allow 24 hours for delivery by email). The report explains how to customize Matlab’s uicontrols in ways that are simply not possible using documented Matlab properties. This includes treatment of push buttons, toggle buttons, radio buttons, checkboxes, editboxes, listboxes, popup menus (aka combo-boxes/drop-downs), sliders, labels, and tooltips. Much of the information in the report is also available in hard-copy format in chapter 6 of my Matlab-Java programming book.

Related posts:

  1. IP address input control – A built-in JIDE control can be used in Matlab GUI for IP-address entry/display. ...
  2. Smart listbox & editbox scrollbars – Matlab listbox and multi-line editbox scrollbars can easily be made smarter, for improved appearance. ...
  3. Customizing listbox & editbox scrollbars – Matlab listbox and multi-line editbox uicontrols have pre-configured scrollbars. This article shows how they can be customized....
  4. Rich Matlab editbox contents – The Matlab editbox uicontrol does not handle HTML contents as do other uicontrols. In this article I show how this limitation can be removed....
  5. ishghandle's undocumented input parameter – The built-in function ishghandle accepts a second input argument with the expected handle type....
  6. Accessing plot brushed data – Plot data brushing can be accessed programmatically using very simple pure-Matlab code...
Callbacks GUI Java uicontrol Undocumented feature
Print Print
« Previous
Next »
7 Responses
  1. Listbox layout customization | Undocumented Matlab November 13, 2013 at 13:08 Reply

    […] written on listboxes in a long while, and since I’ve recently posted on related controls (editbox, combo-box), I thought of following up with an article on customizing Matlab listbox layout. By the […]

  2. David M February 14, 2015 at 14:44 Reply

    For anyone interested in limiting the contents of the editbox in real-time, I recommend using the MaskFormatter wrapped in a JFormattedtextField. Here is an example for a 5 digit zip-code:

    jMaskFormatter = javax.swing.text.MaskFormatter('#####');
    jFormattedTextField = javax.swing.JFormattedTextField(jMaskFormatter);
    javacomponent(jFormattedTextField,[10,10,120,25],gcf);

    jMaskFormatter = javax.swing.text.MaskFormatter('#####'); jFormattedTextField = javax.swing.JFormattedTextField(jMaskFormatter); javacomponent(jFormattedTextField,[10,10,120,25],gcf);

    Info on the MaskFormatter class can be found here:

    http://docs.oracle.com/javase/7/docs/api/javax/swing/text/MaskFormatter.html

  3. Adam August 19, 2015 at 13:19 Reply

    Keeps showing Java exception errors in the Command Window. I have added some null checks into the editboxValidation function but couldn’t stop the error messages being displayed. When I hit a non-numeric character like space or a letter, computer beeps as it should and a long list of Java exception errors are shown in the Command Window. I am copying the error output below. I would appreciate if you could shed a light. Using MATLAB R2014a 32-bit on Windows 7 64-bit machine. Thank you.

    Exception in thread “AWT-EventQueue-0” java.lang.NullPointerException
    at javax.swing.text.DefaultCaret.paint(Unknown Source)
    at javax.swing.plaf.basic.BasicTextUI.paintSafely(Unknown Source)
    at javax.swing.plaf.basic.BasicTextUI.paint(Unknown Source)
    at javax.swing.plaf.basic.BasicTextUI.update(Unknown Source)
    at javax.swing.JComponent.paintComponent(Unknown Source)
    at javax.swing.JComponent.paint(Unknown Source)
    at javax.swing.JComponent.paintToOffscreen(Unknown Source)
    at javax.swing.RepaintManager$PaintManager.paintDoubleBuffered(Unknown Source)
    at javax.swing.RepaintManager$PaintManager.paint(Unknown Source)
    at javax.swing.RepaintManager.paint(Unknown Source)
    at javax.swing.JComponent._paintImmediately(Unknown Source)
    at javax.swing.JComponent.paintImmediately(Unknown Source)
    at javax.swing.RepaintManager.paintDirtyRegions(Unknown Source)
    at javax.swing.RepaintManager.paintDirtyRegions(Unknown Source)
    at javax.swing.RepaintManager.prePaintDirtyRegions(Unknown Source)
    at javax.swing.RepaintManager.access$700(Unknown Source)
    at javax.swing.RepaintManager$ProcessingRunnable.run(Unknown Source)
    at java.awt.event.InvocationEvent.dispatch(Unknown Source)
    at java.awt.EventQueue.dispatchEventImpl(Unknown Source)
    at java.awt.EventQueue.access$200(Unknown Source)
    at java.awt.EventQueue$3.run(Unknown Source)
    at java.awt.EventQueue$3.run(Unknown Source)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.security.ProtectionDomain$1.doIntersectionPrivilege(Unknown Source)
    at java.awt.EventQueue.dispatchEvent(Unknown Source)
    at java.awt.EventDispatchThread.pumpOneEventForFilters(Unknown Source)
    at java.awt.EventDispatchThread.pumpEventsForFilter(Unknown Source)
    at java.awt.EventDispatchThread.pumpEventsForHierarchy(Unknown Source)
    at java.awt.EventDispatchThread.pumpEvents(Unknown Source)
    at java.awt.EventDispatchThread.pumpEvents(Unknown Source)
    at java.awt.EventDispatchThread.run(Unknown Source)

    • b January 8, 2016 at 03:22 Reply

      I have the same issue as Adam. For some reason it helps to display some (invisible) text in the command window before issuing setText(), like so:

      fprintf(repmat(' b',1,500))
      jObj.setText(txt);

      fprintf(repmat(' b',1,500)) jObj.setText(txt);

      This helps preventing the aforementioned NPE in most (but not all) cases. Can anyone explain this?

      MATLAB 2015b 64-bit on Win7 64-bit machine.

    • LSHC October 22, 2021 at 20:55 Reply

      I have the same problem in 2021 haha

  4. Pedro Luis Guevara June 12, 2019 at 18:46 Reply

    Good morning. I have the following problem I have a uitable in main GUI that has “n” rows (the rows depend on the value that the user enters in a text box) and 10 columns. I require a code (something like a keypresskeypress event) that allows me to evaluate and discard the entered data that are not numeric both in the uitable and in some text boxes that I have in the main GUI. I do not know much about event management in MATLAB and I’m having a lot of problems with this. My uitable is called (“TablaDatosElementos”) and the text box that allows creating the number of rows is called (“NumElem”) Thank you very much and I hope you can help me.

    I am a beginner in the use of MATLAB and more when I use tools that are foreign to it (like JAVA). Will it be that one of you can help me design a code for what I need? I can provide lines of the code of the program that I am doing if that helps.

    I hope you can help me with this big problem.

    Thank you

    • Yair Altman June 12, 2019 at 18:49 Reply

      Pedro – I will be happy to assist you as a professional (paid) consultant. Email me if you are interested.

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
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) uitable (6) uitools (20) Undocumented feature (187) Undocumented function (37) Undocumented property (20)
Recent Comments
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