Simply entering the debugger during execution of MATLAB GUI fixes error that persists during normal execution - matlab

I'm using a programmatic GUI in MATLAB which uses multiple figure windows. When I press the button 'Redraw' in Figure A, a new figure appears (Figure B) with some data plotted. I want the focus to immediately switch back to Figure A because there are many hotkeys (WindowKeyPressFcn) that I use in that window to update the plots in Figure B.
There are two problems here:
1) The last line of the callback for the button 'Redraw' does switch focus back to Figure A, BUT only if Figure B exists already. That is, the first time Figure B is created, it remains in focus. If I then use Figure A to update the plots in Figure B, the focus correctly switches back to Figure A. I can't think of why it behaves differently during the first redraw and all subsequent calls.
2) The even bigger issue is that if I set a breakpoint anywhere in the code and then resume execution, the focus switches back to Figure A as I want. So, why does entering the debugger and doing nothing else fix the problem? How can I find the issue if everything works in the debugger?
Thanks in advance!
EDIT: To my great surprise, I was able to reproduce this "Heisenbug" by writing my first ever programmatic GUI. This should be the simplest example of my problem. To see it in action, simply run the code below and click on the push button. For some reason, when Window 2 is created for the first time, the focus does NOT switch back to Window 1 as intended. It works properly for all subsequent button presses. Try closing Window 2 and pushing the button again, the error will keep occurring.
As mentioned in the original post, setting a breakpoint in the code resolves the issue. Set a breakpoint at line 27, then resume execution and Window 1 will be in focus.
What is happening here?
function heisenbug
%% Main problem:
% After clicking the push button, I want the focus to
% always switch back to Window 1 (the one containing the button).
% However, this does not work when Window 2 is first created.
%%
%% Create and then hide the GUI as it is being constructed
f = figure('Visible','off','name','Window 1','units','normalized','Position',[0.1 0.1 0.5 0.5]);
%% Initialize handles structure
handles = guihandles(f);
handles.window2 = [];
guidata(f,handles)
%% Make a button
hbutton = uicontrol('Style','pushbutton','String','Push me','units','normalized',...
'Position',[0.1 0.1 0.8 0.8],...
'Callback',#button_Callback);
%% Make the GUI visible
f.Visible = 'on';
%% Button callback
function button_Callback(source,eventData)
handles = guidata(gcbo);
% If Window 2 already exists, plot a circle, then switch focus back to Window 1.
if ~isempty(handles.window2) && ishandle(handles.window2)
figure(handles.window2);
plot(1,1,'bo')
figure(f);
% Otherwise, create Window 2 and do the same thing.
else
handles.window2 = figure('Name','Window 2','units','normalized','position',[0.4 0.1 0.5 0.5]);
plot(1,1,'bo')
figure(f)
end
guidata(source,handles)
end
end

My post was quickly answered by Adam (thanks!) on the MathWorks site: http://se.mathworks.com/matlabcentral/answers/299607-simply-entering-the-debugger-during-execution-of-matlab-gui-fixes-error-that-persists-during-normal.
I needed to insert a pause(0.05) after Window 2 is created, before trying to switch the focus back with figure(f). Otherwise the focus is stolen back to Window 2 when it finishes plotting.

Related

MATLAB GUI drawnow renderes button 'pushed down' instead of 'disabled'

I am running the drawnow statement from a callback function within a MATLAB GUI to update the state of a button. At the beginning of the callback (which has high runtime) I alter the properties of the button and force an update with drawnow. While updateing properly, the button remains rendered 'pushed down' instead of 'disabled'. After the callback is finished, the button is updated again and now rendered 'disabled'.
Take following minmal (not) working example:
function simple_example()
h = figure();
% add a button, give it some properties and a callback
uicontrol(h,...
'Style','pushbutton',...
'String','I am enabled',...
'Units','normalized',...
'Position',[0.5 0.5 0.4 0.4],...
'Callback',#btn_callback);
end
function btn_callback(hObject, ~)
set(hObject,'Enable','off');
set(hObject,'String','I am disabled');
drawnow;
pause(3);
end
Is there a way to change this behavior and have the button appear disabled while the callback is still executing?
As you are asking about appearance here's a workaround using uibuttongroup:
function simple_example()
h = figure();
b = uibuttongroup('Position',[0.5 0.5 0.4 0.4]);
bgcolor = b.BackgroundColor;
% add a button, give it some properties and a callback
uicontrol(b,...
'Style','pushbutton',...
'String','I am enabled',...
'Units','normalized',...
'Position',[-0.05 -0.05 1.1 1.1],...
'Callback',#btn_callback);
end
function btn_callback(hObject, ~)
set(hObject,'Enable','off');
set(hObject,'String','I am disabled');
drawnow;
pause(3);
end
Here, you fit the button within a uibuttongroup, which normally groups several uibuttons and then set the button size bigger than the actual uibuttongroup, so the borders don't appear.
However, this let's you lose the button down rendering. You could get that back by altering the uicontrolgroup's border properties.
Update:
This seems to be OS-specific. On OS X your code works just fine, as far as I can see. Windows, I don't know, but according to your comment neither my version, nor yours seems to fix the issue. On Ubuntu, on the other hand, my answer solves the problem.

Push button is only changing position once

I have a question about callback functions in MATLAB's GUIDE. I have the following code execute when a button is pushed:
handles.xPos=handles.xPos+1
addX = handles.xPos
handles.shape2 =fill ([-2+addX 1+addX 1+addX -1+addX], [1 1 -1 -1], 'r');
This works, but only once (and the old shape is still there, but that is a separate problem). I have done debugging code and have determined that the callback function is always called when the button is pushed, but for some strange reason there is no effect in the change of the position after the first push of the button.
What am I doing wrong here?
You have to update your handles via guidata to take the modifications of handles into account:
guidata(hObject,handles);
Otherwise the modifications of handles are lost at the end of the callback's execution.
Best

Conditional pausing in Matlab (not Debugging)

I am new to Matlab so please bear with me.
So I created a two GUID GUI in which one generates a dynamic data and updates the plotting every second so I used pause(1) (which is continuous) and the second one takes the full data of the first GUI and plots it (opens on button press)
Is there a way where if I open the the second GUI the first GUI pauses and if and only if the second GUI is stopped the first GUI resumes its process?
Thanks in advance.
Update
Example:
gui1.m
function guie1()
for ii=1:100
c = magic(ii)
plot(c);
% a button at this point
% Some pause condition
drawnow;
end
so when I click on that button it would open a window (a new figure may be) so unless I close is the loop should be paused.
Here is the example:
run(fullfile(docroot,'techdoc','creating_guis','examples','callback_interrupt'));
Here is the link:
http://www.mathworks.com/help/matlab/creating_guis/callback-sequencing-and-interruption.html
Update:
Here:
http://blogs.mathworks.com/videos/2010/12/03/how-to-loop-until-a-button-is-pushed-in-matlab/
http://www.mathworks.com/matlabcentral/fileexchange/29618-spspj

Pressing a button disables keyboard input

I have a strange problem in my Matlab GUI. The GUI contains uipanel and icontrol objects, some of which are buttons. Usually, the GUI is controlled with the directional arrow keys.
However, once I click one of my buttons, the keyboard events are not recorded any more. I've set breakpoints in the keypress callback to find out what's happening and it turns out the callback is never called. If I manage to click the GUI background, it works once again, which makes me think it's related to the active control. But how can I give control back to the main window? uicontrol(hFigure) doesn't work, neither does figure(hFigure).
The following code snippet reproduces the problem. Copy it into a new file (ideally called test.m, otherwise Code Analyzer will complain) and run it to open a GUI window that shows this behaviour. Once the button is clicked, the arrow keys aren't recorded any more unless the user clicks the area outside the text uicontrol.
function test
figure('KeyPressFcn',#key)
clf
p = uipanel('position',[0 0 1 1],'BackgroundColor',[.7 .7 .7]);
uicontrol('Style','push','String','Click me','Units','norm',...
'Position',[0.43 0.91 0.14 0.06],'Callback',#button);
t = uicontrol(p,'Style','text','String','Use arrow keys','Units','norm',...
'Position',[0.2 0.4 0.6 0.2],'FontSize',20);
function button(~,~)
set(t,'String','Button pressed.');
end
function key(~,e)
set(t,'String',['Key ' e.Key ' pressed.']);
end
end
You are right about why this doesn't work. When you click on the button, the figure is no longer the active control. The best way to fix this is to additionally set the KeyPressFcn property of the button to be the same as the KeyPressFcn of the figure.
function test
figure('KeyPressFcn',#key)
clf
p = uipanel('position',[0 0 1 1],'BackgroundColor',[.7 .7 .7]);
uicontrol('Style','push','String','Click me','Units','norm',...
'Position',[0.43 0.91 0.14 0.06],'Callback',#button, ...
'KeyPressFcn', #key);
t = uicontrol(p,'Style','text','String','Use arrow keys','Units','norm',...
'Position',[0.2 0.4 0.6 0.2],'FontSize',20);
function button(~,~)
set(t,'String','Button pressed.');
end
function key(~,e)
set(t,'String',['Key ' e.Key ' pressed.']);
end
end
You could also set the WindowKeyPressFcn instead of KeyPressFcn.
For more information see my answer here:
matlab: difference between KeyPressFcn and WindowKeyPressFcn

MATLAB: Pause program and await keypress

I am writing a program in which at some point a graph is plotted and displayed on screen. The user then needs to press 'y' or 'n' to accept or reject the graph. My current solution uses the PsychToolbox (the actual solution doesn't need to), which includes a command called 'KbCheck' which checks at the time of calling the state of all the keyboard buttons. My code looks like this:
function [keyPressed] = waitForYesNoKeypress
keyPressed = 0; % set this to zero until we receive a sensible keypress
while keyPressed == 0 % hang the system until a response is given
[ keyIsDown, seconds, keyCode ] = KbCheck; % check for keypress
if find(keyCode) == 89 | find(keyCode) == 78 % 89 = 'y', 78 = 'n'
keyPressed = find(keyCode);
end
end
The problem is, that the system really does 'hang' until a key is pressed. Ideally, I would be able to scroll, zoom, and generally interact with the graphs that are plotted onscreen so that I can really decide whether or not I want to press 'y' or 'n'!
I have tried adding 'drawnow;' into the while loop above but that doesn't work: I still am unable to interact with the plotted graphs until after I've accepted or rejected them.
The solution doesn't have to use PsychToolbox; I assume there are plenty of other options out there?
Thanks
I'd use the input function:
a = input('Accept this graph (y/n)? ','s')
if strcmpi(a,'y')
...
else
...
end
Although admittedly it requires two keypresses (y then Enter) rather the one.
Wait for buttonpress opens up a figure, which may be unwanted. Use instead
pause('on');
pause;
which lets the user pause until a key is pressed.
Why not using waitforbuttonpress instead?
Documentation: http://www.mathworks.fr/help/techdoc/ref/waitforbuttonpress.html
You don't want to use waitforbuttonpress since it locks the figure gui (no zooming, panning etc).
pause can cause the command window to steal the focus from the figure.
The solution I find to work best is to open the figure with a null keyPressFcn in order to avoid focus problems:
figure('KeyPressFcn',#(obj,evt) 0);
and then wait for CurrentCharacter property change:
waitfor(gcf,'CurrentCharacter');
curChar=uint8(get(gcf,'CurrentCharacter'));
Wait for key press or mouse-button click:
Example:
w = waitforbuttonpress;
if w == 0
disp('Button click')
else
disp('Key press')
end
for more information visit:
http://www.mathworks.com/help/matlab/ref/waitforbuttonpress.html
The waitforbuttonpress command is good but is triggered by either a mouse click or a key press. If you want it to trigger only from a key press, you can use the following hack:
while ~waitforbuttonpress
end