matlabmatlab-guide

Numeric entry only in edit text MATLAB GUI


I have an edit text in a MATLAB GUI. I want the user to be able to write only numerals and whenever they write a text character, this last character is immediately deleted. Moreover, I don't know in which kind of function to put this code(callback, keypress, etc.).


Solution

  • This is impossible without resorting to Java. That is because MATLAB has no way to access a uicontrol's typed string; you can only access its current string (i.e., after pressing Enter or changing focus).

    Below is an imperfect workaround. It uses two identical edit boxes, one on top of the other, but the topmost box is initially hidden. The KeyPressFcn of the visible edit box:

    1. filters the keypresses on numeric-only
    2. accumulates valid keypresses in a string with global storage
    3. sets that string to the current string of the invisible edit box
    4. Makes that invisible edit box visible, so that it occludes the one you're typing in

    Its CallBack function then

    1. Takes the string of the normally-invisible box
    2. Sets the always-visible box' string equal to that string
    3. Hides the normally-invisible box again

    Here's the implementation (liberally borrowed from here):

    function GUI_tst
    
        % Create new GUI
        G.fh = figure('menubar' , 'none',...
                      'units'   , 'normalized', ...
                      'position', [.4 .4 .2 .2]);
    
        % The actual edit box
        G.eh1 = uicontrol('style'      , 'edit',...
                         'units'      , 'normalized', ...
                         'position'   , [.1 .4 .8 .2],...
                         'string'     , '',...
                         'KeyPressFcn', @kpr,...
                         'Callback'   , @cll);
    
        % The "fake" edit box      
        G.eh2 = copyobj(G.eh1, G.fh);
        set(G.eh2, 'Visible', 'off');
    
        % Its string (global)       
        G.eh_str = '';
    
    
        guidata(G.fh, G);
    
    end
    
    
    % "Real" edit box' KeyPressFcn()   
    function kpr(~, evt)
    
        if isempty(evt.Character)
            return; end
    
        G = guidata(gcbf);
    
        % Occlude the "real" editbox with the "fake" one
        set(G.eh2, 'visible', 'on');
    
        % Accumulate global string if keys are numeric
        if strcmp(evt.Key,'backspace')
            G.eh_str = G.eh_str(1:end-1);
    
        elseif isempty(evt.Modifier) && ...
               any(evt.Character == char((0:9)+'0') )
    
            G.eh_str = [G.eh_str evt.Character];        
        end
    
        % Set & save new string
        set(G.eh2, 'string', G.eh_str);
        guidata(gcbf,G);
    
    end
    
    
    % "Real" edit box' CallBack()   
    function cll(~,~)    
        G = guidata(gcbf);   
    
        % Set the "real" box' string equal to the "fake" one's, 
        % and make the "fake" one invisible again
        set(G.eh1, 'String', get(G.eh2, 'String'));
        set(G.eh2, 'visible', 'off');
    end
    

    This works reasonably well, but it has some drawbacks:

    Although it is possible using Java (see this post by MATLAB-god Yair Altman), the simpler and more common way to do it is to just accept that the user is typing invalid input, and only check/correct it in the Callback function (i.e., after pressing Enter).