Block GUI in Callback
    3 visualizzazioni (ultimi 30 giorni)
  
       Mostra commenti meno recenti
    
Dear all,
how can I block interaction with a GUI, while a callback is executed. I'd like to create a GUI where by clicking a button a dialog to select a file opens and afterwards something is done to the file that is pretty time-consuming. Suprisingly, the callback is somehow executed in parallel, so it doesn't automatically block execution and this leads to undesired behaviour, because you could open the file-open-dialog again and I'd prefer to make this less annoying.
For illustration I created a small class:
classdef testGUI < handle
    properties(Access = private)
        hMainFigure
    end
    methods(Access = public)
        function this = testGUI()
            this.hMainFigure = figure('Visible', 'off');
            uicontrol('Style', 'pushbutton', 'String', 'Test', 'Callback', @this.testCallback, 'Parent', this.hMainFigure, 'Units', 'normalized', 'Position', [0,0,1,1]);
            this.hMainFigure.Visible = 'on';
        end
    end
    methods(Access = private)
        function testCallback(~, ~, ~)
            % -- deactivate main figure
            pause(2);
            % -- activate main figure
            fprintf('test\n');
        end
    end
end
If you click the button, the callback is executed and you can immediately click the button again - I would like to block the entire GUI until the callback (here the pause) is finished.
Thanks in advance,
Torsten
0 Commenti
Risposta accettata
  Geoff Hayes
      
      
 il 23 Apr 2020
        Torsten - you could disable the button so that it can't be pressed again
        function testCallback(~, hButtonObj, ~)
            % -- deactivate main figure
            set(hButtonObj, 'Enable', 'off');   % <----- disable button
            pause(2);
            % -- activate main figure
            fprintf('test\n');
            set(hButtonObj, 'Enable', 'on');    % <----- enable button
        end
Of course, if you have several buttons or fields, you would need to block all of them too. Or consider using a Indeterminate Progress Bar....I think it is modal so while it is present, the user shouldn't be able to interact with your GUI.
6 Commenti
Più risposte (1)
  Rik
      
      
 il 24 Apr 2020
        
      Modificato: Rik
      
      
 il 24 Apr 2020
  
      %appdata is the guidata struct (which I now think was a poor choice as a name)
ButtonCallbackBuzy=appdata.ButtonCallbackBuzy;
if ButtonCallbackBuzy
    return%ignore key presses if a callback is already in progress
else
    appdata.ButtonCallbackBuzy=true;
    guidata(appdata.fig,appdata);
end
You do need to carefully keep track of when you load and save the guidata struct.
It might be a better idea to write a getter and setter function to do it:
%in your functions that need to check if the busy flag is set:
if getIfBusyFlag(gcbf)
    return%ignore
else
    setIfBusyFlag(gcbf,true)
end
%long running code
setIfBusyFlag(gcbf,false)
%getter and setter
function isBusy=getIfBusyFlag(hfig)
isBusy=false;
if ~isappdata(hfig,'isBusy')
    setappdata(hfig,'isBusy',isBusy);
else
    isBusy=getappdata(hfig,'isBusy');
end
end
function setIfBusyFlag(hfig,isBusy)
setappdata(hfig,'isBusy',isBusy);
end
3 Commenti
  Rik
      
      
 il 28 Apr 2020
				That is of course your call, although I doubt this will cause a lot of overhead. You could time how long these function take, but it is up to you to decide if that performance penalty is worth it.
Vedere anche
Categorie
				Scopri di più su Loops and Conditional Statements in Help Center e File Exchange
			
	Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!