GUI with Matlab: A Tutorial

1. Introduction


2. GUI elements


3. Finding out more about GUI elements


4. Simplest GUI: message box

msgbox('I am afraid I CAN do that, Mik.')


5. Simpler GUI: input box

prompt={'name', 'function to call', 'number'}
defans={'mik', 'hamming', '123'}
fields = {'name','func', 'num'}
info = inputdlg(prompt, 'give it to me!', 1, defans)
if ~isempty(info)              %see if user hit cancel
   info = cell2struct(info,fields)
   myname = info.name
   myfunc = info.func
   mynum = str2num(info.num)   %convert string to number
   mycall = [myfunc '(' num2str(mynum) ')']
   eval(mycall)                %evaluate expression
   msgbox([myname ', I hope ' mycall ' was what you wanted.'], 'Cool!')
end
%you can and should put ; on all line endings in practical program
%also, str2num and num2str are not necessary, just there for demo purpose


6. Simple GUI generation


7. Analysis of simple GUI code 1

function test()
% This is the machine-generated representation of a MATLAB object
% and its children.  Note that handle values may change when these
% objects are re-created. This may cause problems with some callbacks.
% The command syntax may be supported in the future, but is currently 
% incomplete and subject to change.
%
% To re-open this system, just type the name of the m-file at the MATLAB
% prompt. The M-file and its associtated MAT-file must be on your path.
load test


8. Analysis of simple GUI code 2

a = figure('Color',[0.8 0.8 0.8], ...
        'Colormap',mat0, ...
        'PointerShapeCData',mat1, ...
        'Position',[564 166 672 504], ...
        'Tag','Fig1');


9. Analysis of simple GUI code 3

b = uicontrol('Parent',a, ...
         'Units','points', ...
         'Callback','msgbox(''hello mik'')', ...
         'Position',[124.759 62.6897 83.1724 30.4138], ...
         'String','greetings', ...
         'Tag','Pushbutton1');


10. Analysis of simple GUI code 4

function test1()
uicontrol('style', 'pushbutton', ...
        'parent', figure, ...
        'string', 'greetings', ...
        'callback','msgbox(''hello mik'')', ...
        'position', [10 10 100 30]);
return


11. Analysis of simple GUI code 5: summary


12. List of properties for UIcontrol


13. Useful simple GUI commands

plot(sin(0:.1:20));
zoom on
[x y] = ginput(1);
txthandle = text(x, y, [num2str(x) ', ' num2str(y)]);
set(txthandle, 'rotation', 45);
x = 0:.01:.6;
[x y] = meshgrid(x,x);
z = sin(x^2 - y^2);
surf(x, y, z);
rotate3d on;


14. Sophisticated GUI program


15. Using recursion

function recurs(param)
switch param
case 'first'
   msgbox('this is 1');
   recurs('second');
case 'second'
   msgbox('this is 2');
otherwise
   msgbox('this is zero');
   recurs('first');
end
return


16. Parameters to recursion

function recurs(param)
if nargin == 0
   param = '???';
end

switch param
case 'first'
   msgbox('this is 1');
   recurs('second');
case 'second'
   msgbox('this is 2');
otherwise
   msgbox('this is zero');
   recurs('first');
end
return


17. Using global variables

function recurs(param)
global x y z;
if nargin == 0
   param = '???';
end

switch param
.
.
.
return


18. Sophisticated program example


19. Create buttons


20. Give meaningful names to buttons

function gpgp()
global hbtn_plotval hbtn_remove hbtn_removeall hbtn_edit hbtn_zoom hbtn_quit;


21. Position buttons

btnlef = 2.48276;
btnbot = 3.10345;
btnwid = 47.1724;
btnhei = 14.8966;
'Position',[btnlef+0*btnwid btnbot btnwid btnhei], ...
'Position',[btnlef+1*btnwid btnbot btnwid btnhei], ...
'Position',[btnlef+2*btnwid btnbot btnwid btnhei], ...
'Position',[btnlef+3*btnwid btnbot btnwid btnhei], ...
'Position',[btnlef+4*btnwid btnbot btnwid btnhei], ...
'Position',[btnlef+5*btnwid btnbot btnwid btnhei], ...


22. Change the function for recursion

function gpgp(param)
global hbtn_plotval hbtn_remove hbtn_removeall hbtn_edit hbtn_zoom hbtn_quit;

if nargin == 0
   param = 'init';
end
{rest of the code from previous step}
switch(param)
case 'init'
   btnlef = 2.48276;
.
.
.
{make button routines from previous step}
end
return


23. Source code so far

function gpgp(param)
global hbtn_plotval hbtn_remove hbtn_removeall hbtn_edit hbtn_zoom hbtn_quit;

if nargin == 0
   param = 'init';
end

switch(param)
case 'init'
   btnlef = 2.48276;
   btnbot = 3.10345;
   btnwid = 47.1724;
   btnhei = 14.8966;
   hbtn_plotval = uicontrol('Parent',gcf, ...
      'Units','points', ...
      'Position',[btnlef+0*btnwid btnbot btnwid btnhei], ...
      'String','PlotVal');   
   hbtn_remove = uicontrol('Parent',gcf, ...
      'Units','points', ...
      'Position',[btnlef+1*btnwid btnbot btnwid btnhei], ...
      'String','Remove');
   hbtn_removeall = uicontrol('Parent',gcf, ...
      'Units','points', ...
      'Position',[btnlef+2*btnwid btnbot btnwid btnhei], ...
      'String','RemoveAll');
   hbtn_edit = uicontrol('Parent',gcf, ...
      'Units','points', ...
      'Position',[btnlef+3*btnwid btnbot btnwid btnhei], ...
      'String','Edit');
   hbtn_zoom = uicontrol('Parent',gcf, ...
      'Units','points', ...
      'Position',[btnlef+4*btnwid btnbot btnwid btnhei], ...
      'String','Zoom Off');
   hbtn_quit = uicontrol('Parent',gcf, ...
      'Units','points', ...
      'Position',[btnlef+5*btnwid btnbot btnwid btnhei], ...
      'String','Quit');
end
return


24. Method for PlotVal button

   hbtn_plotval = uicontrol('Parent',gcf, ...
      'Units','points', ...
      'Position',[btnlef+0*btnwid btnbot btnwid btnhei], ...
      'String','PlotVal', ...
      'callback', 'gpgp(''hbtn_plotval_click'');');
case 'hbtn_plotval_click'
   [x y] = ginput(1);
   if isempty(x)
      return;
   end
   txt = [num2str(x) num2str(y)];
   text(x, y, txt);


25. Keeping track of text object

   text(x, y, txt);
gets replaced with
   htxt = [htxt text(x, y, txt)];


26. Method for RemoveAll button

   hbtn_removeall = uicontrol('Parent',gcf, ...
      'Units','points', ...
      'Position',[btnlef+2*btnwid btnbot btnwid btnhei], ...
      'String','RemoveAll', ...
      'callback', 'gpgp(''hbtn_removeall_click'');');
case 'hbtn_removeall_click'
   delete(htxt(ishandle(htxt)));
   htxt = [];


27. Method for Quit button

   hbtn_quit = uicontrol('Parent',gcf, ...
      'Units','points', ...
      'Position',[btnlef+5*btnwid btnbot btnwid btnhei], ...
      'String','Quit', ...
      'callback', 'gpgp(''hbtn_quit_click'');');
case 'hbtn_quit_click'
   delete(hbtn_plotval);
   delete(hbtn_remove);
   delete(hbtn_removeall);
   delete(hbtn_edit);
   delete(hbtn_zoom);
   delete(hbtn_quit);
   clear global hbtn_plotval;
   clear global hbtn_remove;
   clear global hbtn_removeall;
   clear global hbtn_edit;
   clear global hbtn_zoom;
   clear global hbtn_quit;
   htxt(~ishandle(htxt)) = [];
   if isempty(htxt)
      clear global htxt;
   end


28. Summary of easy buttons, PlotVal, RemoveAll, Quit

function gpgp(param)
global hbtn_plotval hbtn_remove hbtn_removeall hbtn_edit hbtn_zoom hbtn_quit htxt;

if nargin == 0
   param = 'init';
end

switch(param)
case 'init'
   btnlef = 2.48276;
   btnbot = 3.10345;
   btnwid = 47.1724;
   btnhei = 14.8966;
   hbtn_plotval = uicontrol('Parent',gcf, ...
      'Units','points', ...
      'Position',[btnlef+0*btnwid btnbot btnwid btnhei], ...
      'String','PlotVal', ...
      'callback', 'gpgp(''hbtn_plotval_click'');');
   hbtn_remove = uicontrol('Parent',gcf, ...
      'Units','points', ...
      'Position',[btnlef+1*btnwid btnbot btnwid btnhei], ...
      'String','Remove');
   hbtn_removeall = uicontrol('Parent',gcf, ...
      'Units','points', ...
      'Position',[btnlef+2*btnwid btnbot btnwid btnhei], ...
      'String','RemoveAll', ...
      'callback', 'gpgp(''hbtn_removeall_click'');');
   hbtn_edit = uicontrol('Parent',gcf, ...
      'Units','points', ...
      'Position',[btnlef+3*btnwid btnbot btnwid btnhei], ...
      'String','Edit');
   hbtn_zoom = uicontrol('Parent',gcf, ...
      'Units','points', ...
      'Position',[btnlef+4*btnwid btnbot btnwid btnhei], ...
      'String','Zoom Off');
   hbtn_quit = uicontrol('Parent',gcf, ...
      'Units','points', ...
      'Position',[btnlef+5*btnwid btnbot btnwid btnhei], ...
      'String','Quit', ...

      'callback', 'gpgp(''hbtn_quit_click'');');
   
case 'hbtn_plotval_click'
   [x y] = ginput(1);
   if isempty(x)
      return;
   end
   txt = [num2str(x) num2str(y)];
   htxt = [htxt text(x, y, txt)];
   
case 'hbtn_removeall_click'
   delete(htxt(ishandle(htxt)));
   htxt = [];
   
case 'hbtn_quit_click'
   delete(hbtn_plotval);
   delete(hbtn_remove);
   delete(hbtn_removeall);
   delete(hbtn_edit);
   delete(hbtn_zoom);
   delete(hbtn_quit);
   clear global hbtn_plotval;
   clear global hbtn_remove;
   clear global hbtn_removeall;
   clear global hbtn_edit;
   clear global hbtn_zoom;
   clear global hbtn_quit;
   htxt(~ishandle(htxt)) = [];
   if isempty(htxt)
      clear global htxt;
   end
   
end
return


29. Enhancement to creation

case 'init'
   if ishandle(hbtn_plotval)
      delete(hbtn_plotval);
      delete(hbtn_remove);
      delete(hbtn_removeall);
      delete(hbtn_edit);
      delete(hbtn_zoom);
      delete(hbtn_quit);
   end
   zoom off;
.
.
.


30. Method for Zoom button

   hbtn_zoom = uicontrol('Parent',gcf, ...
      'Units','points', ...
      'Position',[btnlef+4*btnwid btnbot btnwid btnhei], ...
      'String','Zoom Off', ...
      'callback', 'gpgp(''hbtn_zoom_click'');');
case 'hbtn_zoom_click'%error: zoom will distort movement and remove/edit
   a_str = get(hbtn_zoom, 'string');
   switch a_str
   case 'Zoom Off'
      zoom on;
      set(hbtn_zoom, 'string', 'Zoom On');
   otherwise
      zoom off;
      set(hbtn_zoom, 'string', 'Zoom Off');
   end


31. Method for Remove button

   hbtn_remove = uicontrol('Parent',gcf, ...
      'Units','points', ...
      'Position',[btnlef+1*btnwid btnbot btnwid btnhei], ...
      'String','Remove', ...
      'callback', 'gpgp(''hbtn_remove_click'');');
case 'hbtn_remove_click'
   if ~ishandle(htxt)
      return
   end   
   set(gcf, 'pointer', 'crosshair');
   set(htxt, 'ButtonDownFcn', 'gpgp(''fcn_removetxt'')');
case 'fcn_removetxt'
   set(gcf, 'pointer', 'arrow');
   set(htxt, 'ButtonDownFcn', 'gpgp(''fcn_text_click'');');
   htxt(htxt == gcbo) = [];
   delete(gcbo);


32. Method for Edit button

   hbtn_edit = uicontrol('Parent',gcf, ...
      'Units','points', ...
      'Position',[btnlef+3*btnwid btnbot btnwid btnhei], ...
      'String','Edit', ...
      'callback', 'gpgp(''hbtn_edit_click'');');
case 'hbtn_edit_click'
   if ~ishandle(htxt)
      return
   end   
   set(gcf, 'pointer', 'Ibeam');
   set(htxt, 'ButtonDownFcn', 'gpgp(''fcn_edittxt'')');
   
case 'fcn_edittxt'
   obj = gcbo;
   txt = {get(obj, 'string')};
   txtcell = inputdlg({'What is thy bidding, my master?'}, ...
      'New text value', 1, txt);
   set(gcf, 'pointer', 'arrow');
   set(htxt, 'ButtonDownFcn', 'gpgp(''fcn_text_click'');');
   if isempty(txtcell)
      return
   end
   txt = cell2struct(txtcell, {'txt'}, 1);
   set(obj, 'string', txt.txt);


33. Dragging text around

case 'hbtn_plotval_click'
   [x y] = ginput(1);
   if isempty(x)
      return;
   end
   txt = [num2str(x) ', ' num2str(y)];
   txt = text(x, y, txt);
   set(txt, 'ButtonDownFcn', 'gpgp(''fcn_text_click'');');
   htxt = [htxt txt];
   htxt(~ishandle(htxt)) = [];
case 'fcn_text_click'
   obj = gcf;
   set(obj, 'userdata', gcbo);
   set(obj, 'windowbuttonmotionfcn', 'gpgp(''fcn_text_drag'')');
   set(obj, 'windowbuttonupfcn', 'gpgp(''fcn_text_drag_end'')');
case 'fcn_text_drag'
   objfig = gcf;
   pt = get(gca, 'CurrentPoint');
   pt = pt(1, 1:2);
   objtxt = get(objfig, 'userdata');
   set(objtxt, 'position', pt);
case 'fcn_text_drag_end'
   objfig = gcf;
   set(objfig, 'windowbuttonmotionfcn', '');
   set(objfig, 'windowbuttonupfcn', '');


34. Enhancements needed: left as exercise for the reader

  • When figure is closed, all objects are deleted but the global variables remain
  • Moving the text around in zoom mode can cause confusion
  • When remove or edit is clicked and then new plot values is clicked without deleting a value, the new text objects don't initially behave the same as old ones
  • Consolidate all global variables into one global structure
  • Even better, get rid of all global variables in favor of using user data and/or children properties

  • 35. Conclusion