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
Related
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.
I'm writing a matlab program and I'm trying to pass around my handles struct to ALL my callbacks. The only problem is that I'm using GUIDE and I can't pass in handles as an argument to a function I created:
%The proper slider callback: Deleted the default within GUIDE
function sliderContValCallback(hFigure,eventdata)
%test it out- get the handles object and dispay the current value
%getappdata(handles.video_loader_button,'handles');
handles = guidata(hFigure);
handles.currentFrame = floor(get(handles.slider,'Value'));
set(handles.frameBox,'String',num2str(handles.currentFrame));
fprintf('slider value: %f\n',get(handles.slider,'Value'));
updateAxes(handles);
The problem is that the way I'm 'getting' handles right now is that it isn't really the same handles that the rest of the UI object callback functions are using. I also thought of passing handles around with getappdata, but you need handles to even do that so I'm stuck. This has been causing some problems, any help as to how to get around this would be awesome, thanks!
EDIT:
I deleted the call back generated by GUIDE, so that I could use sliderContValCallback as a function handle and call it here:
handles.sliderListener = addlistener(handles.slider,'ContinuousValueChange',...
#(hFigure,eventdata) sliderContValCallback(hObject,eventdata));
for continuous updates as the user drags the slider(This is used to scroll through a video, and its working well).
The real reason I'm questioning this is because when I call:
allCoords = getappdata(handles.axes1,'mydata');
coordsXYZ = allCoords.clickcoordinates; %Do this to access the field 'allCoords' within 'mydata'
curIndex = allCoords.currentIndex;
if numel(coordsXYZ)>0
for i = 1:length(coordsXYZ)
coordXY = [coordsXYZ(i).x,coordsXYZ(i).y];
%viscircles(handles.axes1,coordXY,1,'EdgeColor','r');
hold on;
plot(coordsXYZ(i).x,coordsXYZ(i).y,'o');
end
end
everything works but a figure is generated for some reason, the plot is drawn to an image on handles.axes1. It's weird because this random figure pops up ONLY when I update the slider by moving it.
I've written a Matlab program which counts different values when are particular button is pressed (so far just the numbers of "yes" and "no"). I'm trying to add a key listener so that when I press, for example, n on the keyboard the button is pressed, or the same actions are completed. I have tried the addListener and keyfunclistener functions but neither seems to be working.
Here is an example of the button:
no=uicontrol(h_fig,'callback',countnonerve,'position',[.65 .07 .1 .08],'string','No','style','pushbutton','Units','normalized');
Any suggestions? It would be very helpful I'm not familiar with MatLab
You could try using the KeyPressFcn property of the figure to record/capture individual key presses:
function keypress_Test
h = figure;
set(h,'KeyPressFcn',#keyPressCb);
function keyPressCb(src,evnt)
disp(['key pressed: ' evnt.Key]);
end
end
The above code can be pasted into a file and saved as keypress_Test.m. A figure is created and a callback assigned to the KeyPressFcn property.
It can be easily adapted for your GUI. Wherever you have access to the figure handles (probably the h_fig from above) just add set(h_fig,'KeyPressFcn',#keyPressCb); and paste the keyPressCb code into the same file.
If you are counting the number of times a certain key is pressed, then you will have to save this information somewhere..probably to the handles structure. Is that the case? If so, then you can easily access this from the callback
function keyPressCb(src,evnt)
disp(['key pressed: ' evnt.Key]);
% get the handles structure
handles = guidata(src);
if ~isempty(handles)
% do something here - increment count for evnt.Key
% save the updated count
guidata(src,handles);
end
end
Try it out and see what happens!
I have a checkbox on GUI that draws a rectangle on a live video feed, however, I need the rectangle to dissapear or be deleted when I uncheck it.
does anyone have any idea how to do this?
This is my code, I have tried putting things in else, but nothing works.
function Box(hObject,eventdata)
if (((get(hObject,'Value') == get(hObject,'Max'))))
% Checkbox is checked-take appropriate action
hold on;
rectangle('Position',[50,50,100,100],'EdgeColor','r')
else
end
You need to save the handle created by the function rectangle. Then add this handle to the big handle of your GUI so that you are able to have access to it once the callback is called again.
So modify your function like so
function Box(hObject,eventdata,handles)
if (((get(hObject,'Value') == get(hObject,'Max'))))
% Checkbox is checked-take appropriate action
hold on;
handles.rectangleSave=rectangle('Position',[50,50,100,100],'EdgeColor','r');
guidata(handles.output,handles);
else
delete(handles.rectangleSave);
end
If you have never used handles, please have a look here :
http://www.matlabtips.com/on-handles-and-the-door-they-open/
handles.output usually stores the handle to the big interface window as explained here :
http://www.matlabtips.com/guide-me-in-the-guide/
I'm working on a gui using GUIDE in MATLAB, and from what I've read it looks like MATLAB updates the UI controls based on a timer every so often. Is there a way to force it to update the UI controls, so I can make it update in the middle of the function? Right now I have a function that does, simplifed, something like
set(handles.lblStatus,'String','Processing...')
%function that takes a long time
set(handles.lblStatus,'String','Done')
Since MATLAB doesn't update the GUI during a Callback function, the user only ever sees 'Done' after a long period of waiting and never sees 'Processing'. I tried adding guidata(hObject, handles) after the first set, hoping it would force the screen to update, but it doesn't.
Try calling DRAWNOW.
set(handles.lblStatus,'String','Processing...')
drawnow
%function that takes a long time
set(handles.lblStatus,'String','Done')
I believe there is a drawnow function in matlab.
drawnow completes pending drawing events