Matlab GUI:Setting Current Axes creates a new figure - matlab

I have created a GUI with 3 axes: axes1, axes2, axes3. I have a class SP to whose constructor I pass the three axes as follows:
a=SP(handles.axes1,handles.axes2,handles.axes3)
The class looks something like
class SP < handles
properties
axes1
axes2
axes3
end
methods
function A=SP(axes1,axes2,axes3)
A.axes1=axes1;
A.axes2=axes2;
A.axes3=axes3;
axes(A.axes1);
rectangle('Position',[randn,randn,randn,randn]);
axes(A.axes2);
rectangle('Position',[randn,randn,randn,randn]);
axes(A.axes3);
rectangle('Position',[randn,randn,randn,randn]);
end
I have written a timer function
function timerfcn1(~,~,A)
axes(A.axes1);
rectangle('Position',[randn,randn,randn,randn]);
axes(A.axes2);
rectangle('Position',[randn,randn,randn,randn]);
axes(A.axes3);
rectangle('Position',[randn,randn,randn,randn]);
end
My problem is that during the initialization i.e when i call the constructor, the rectangles are plotted in the GUI window. However, whenever the timerfcn1 runs it creates a new figure and plots the rectangle in that.
I had used a similar thing before and it used to work then.

Most likely it's related to handle visibility (or lack of) in a part of the code that you haven't shown. To guarantee that the rectangle goes to the axis you want use,
rectangle('Position',[...],'Parent',A.axes1)
Before this you should also check that the handle still exists using
if ishandle(A.axes1)
...
end

Related

MATLAB - axes handle get deleted if subplot is created inside class constructor

I'm refactoring an existing (working) MATLAB code, in particular I'm extracting a new class from a piece of structured code that creates a figure, and when I do that, I get an error caused by axes of the figure getting deleted (my variable now says it contains a handle to deleted axes).
In more detail, the current version of the code does something like this:
Overlay = figure
overlayAxes = subplot(1, 2, 1, 'Parent', Overlay)
... (other stuff)
imshow(... other parameters ..., overlayAxes)
(I'm mentioning "other stuff" and "other parameters" to clarify the imshow line is not directly above the overlayAxes assignment, just in case you think I should look for anything in particular before the call to imshow)
This works fine. My refactor is consists in moving the creation of Overlay to a class (in other words, make it more "OOP-like"). As a first step, I moved it to a class like this:
classdef MyGUI < handle
properties(SetAccess = public)
Overlay
overlayAxes
end
methods
function obj = MyGUI()
obj.Overlay = figure;
obj.overlayAxes = subplot(1, 2, 1, 'Parent', obj.Overlay);
end
end
end
And then I referenced this new class where Overlay was originally created like this:
GUI = MyGUI;
Overlay = GUI.Overlay;
overlayAxes = GUI.overlayAxes;
(I made those two variable assignments so I didn't have to change the rest of the code right now - because it references Overlay not GUI.Overlay - in particular the call to imshow)
So, when I do this, the call to imshow fails saying:
Error using imshow>validateParent (line 375)
HAX must be a valid axes handle.
As it turns out, when I debug and inspect overlayAxes, it says it contains a handle to deleted axes.
I've read some articles explaining that axes get deleted when new figures are created and such, but the only change I'm making is converting the figure creation from a local variable to a class property, so I don't feel like is something related to side-effects of calling plot functions again or anything like that, but maybe something about passing by reference, object lifecycle, or something that I'm missing completely, not really sure.
Why are my axes getting deleted? Thanks!

How to return values from an inline function in MATLAB?

I have the following script:
im = imagesc(anImage, 'parent', gca);
set(im,'HitTest','off');
set(gca,'buttondownfcn', #someFunction)
My problem is that I want someFunction to return some values, but I am not sure how to do it in THIS particular scenario. It seems like the inline-ness is not letting me do this...
Thanks.
To make someFunction() set a value in your base workspace (I assume that is what you want to achieve), you can use the assignin() function.
An example for someFunction() that sets the variable axes_position to the the current axes' position is the following
function someFunction(hObject, event)
assignin('base', 'axes_position', get(hObject, 'Position'));
Have a look at the axis and figure properties pages in the MATLAB user guide on how to deal with user UI input in axes and figure controls (not enough reputation to add two more links).
However, you mention that you want to manipulate it in the next line of the program. If I understand correctly, this is what the guidata function is meant for: "store or retrieve UI data".

Communication between two or more GUIs

I've a GUI(i.e. lets call it 'First')through which i can choose to open other GUIs(let's call them 'Second' and 'Third').I want to put a 'pushbutton' on the 'First'GUI that allows me to manipulate the figure on the different axes of the 'Second' and 'Third' GUIs. So, i choose with the 'First'GUI if use either 'Second' or 'Third' GUI; once i've chosen that i start to work just with the GUI that i chose (so the Third one or Second ones). Now i want to have a pushbutton not on each GUIs (Second or Third) but only on the First one in order to manipulate the figure on the axes 1 of the Second or Third (depends on which one i've previously chosen). Furthermore this pushbutton that i want is optional and i need to refresh my axes after used that.
I've done my best to explain the situation,please if you know any solution help me out!!Thanks
Your question is similar to other examples, such as this.
To understand how to solve your problem, you need to remember that MATLAB "decides" which axes to update based on the axes handle provided by the user. If the user doesn't provide a handle, a default gca (the current axes) is used. The axes that gca points to, is the first child of type 'axes' of the figure, that is, the first entry in findobj(hFigure,'Type','axes'). You can read about setting the current axes here.
Having established that, the solution you are looking for would involve storing the axes handles somewhere, and retrieving the correct one when you are about to update a plot. A common place to store it is the "application-defined data" (appdata), accessible by setappdata and getappdata, as mentioned in the first link above and also here.
The procedure you should undergo is:
Upon creating a figure, store the axes handle in appdata by calling setappdata(0,name,val) (e.g. setappdata(0,'axTag1',handles.axTag1)) from your GUI initialization function. The value 0 for the 1st argument stores it in MATLAB's root object (you can think of it as the main MATLAB window), so that even if any of the figures is closed, the information is maintained as long as MATLAB is still open.
Whenever you want to modify an axes, just obtain the appropriate handle using value = getappdata(0,name) and use it to update the corresponding axes.

Expression not evaluated at callback statement

I am building a GUI in Matlab that plots different functions in different plots according to the selected RadioButton. It looks like:
I want to select at which axes should the function be plotted. Therefore I need to know which of the RadioButton is selected. Then:
% Set default RadioButton
set(h.r1,'Value',1);
set(h.r2,'Value',0);
set(h.r1,'Callback',{#myRadioButton, h.r2}); % Set the other RadioButton to false
set(h.r2,'Callback',{#myRadioButton, h.r1}); % Set the other RadioButton to false
Then I call press one of any Button and call my plotting function which (should) evaluate(s) which axes it has to use:
set(h.b1,'Callback',{#myPlotFunction,...
get(h.r1,'value')*h.axes1+get(h.r2,'value')*h.axes2, h.x});
The problem is that I always get h.axes1 as input, no matter which RadioButton I choose.
Is this due to the definition of default values for RadioButton?
EDIT
Another edit: Ok, now we're dynamically assigning the button handles and xdata inside of the radiobutton callback.
Due to some peculiarities with MATLABs handling of function handle arguments (see comments), my first answer doesn't work. This one does.
set(h.r1,'Callback',{#TurnOffRadio, h.r2, h.axes1, h.x});
set(h.r2,'Callback',{#TurnOffRadio, h.r1, h.axes2, h.x});
function TurnOffRadio(hObject, eventdata, radiohandle, axeshandle, xdata)
set(radiohandle, 'Value', 0);
set(h.b1,'Callback',{#myPlotFunction, axeshandle, xdata});
%// Repeat set statement for each button.
end %// You may nee to remove this end, depending on your conventions.
function myPlotFunction(hObject, eventdata, axeshandle, xdata)
%// do whatever here with axeshandle and xdata.
end %// You may nee to remove this end, depending on your conventions.
I've set up a toy example and run this exact code, and it produces the desired effect.
Let me know if this still doesn't solve the problem, and I'll keep digging.
Original
You're close. The problem is that when you set a callback function using a function handle and arguments, the arguments always remain what they were at the time that the callback was set. Essentially, they are passed only once, not dynamically each time the callback is executed. To work around this, just set the callback to turn off the other radio button directly using set.
set(h.r1,'Callback',{#set, h.r2, 'Value', 0});
set(h.r2,'Callback',{#set, h.r1, 'Value', 0});
Let me know if that doesn't work for you. Good luck!

Does Matlab execute a callback when a plot is zoomed/resized/redrawn?

In Matlab, I would like to update the data plotted in a set of axes when the user zooms into the plot window. For example, suppose I want to plot a particular function that is defined analytically. I would like to update the plot window with additional data when the user zooms into the traces, so that they can examine the function with arbitrary resolution.
Does Matlab provide hooks to update the data when the view changes? (Or simply when it is redrawn?)
While I have yet to find one generic "redraw" callback to solve this question, I have managed to cobble together a group of four callbacks* that seem to achieve this goal in (almost?) all situations. For a given axes object ax = gca(),
1. Setup the zoom callback function as directed by #Jonas:
set(zoom(ax),'ActionPostCallback',#(x,y) myCallbackFcn(ax));
2. Setup a pan callback function:
set(pan(ax),'ActionPostCallback',#(x,y) myCallbackFcn(ax));
3. Setup a figure resize callback function:
set(getParentFigure(ax),'ResizeFcn',#(x,y) myCallbackFcn(ax));
4. Edit: this one no longer works in R2014b, but is only needed if you add, e.g., a colorbar to the figure (which changes the axis position without changing the figure size or axis zoom/pan). I've not looked for a replacement. Finally, setup an undocumented property listener for the axes position property itself. There is one important trick here: We must hold onto the handle to the handle.listener object as once it's deleted (or leaves scope), it removes the callback. The UserData property of the axes object itself is a nice place to stash it in many cases.
hax = handle(ax);
hprop = findprop(hax,'Position');
h = handle.listener(hax,hprop,'PropertyPostSet',#(x,y) myCallbackFcn(ax));
set(ax,'UserData',h);
In all these cases I've chosen to discard the default callback event arguments and instead capture the axis in question within an anonymous function. I've found this to be much more useful than trying to cope with all the different forms of arguments that propagate through these disparate callback scenarios.
*Also, with so many different callback sources flying around, I find it invaluable to have a recursion check at the beginning of myCallbackFcn to ensure that I don't end up in an infinite loop.
Yes, it does. The ZOOM mode object has the following callbacks:
ButtonDownFilter
ActionPreCallback
ActionPostCallback
The latter two are executed either just before or just after the zoom function. You could set your update function in ActionPostCallback, where you'd update the plot according to the new axes limits (the handle to the axes is passed as the second input argument to the callback).