I have a very simple GUI made in guide where i have a plot function initiated by a pushbutton which plots a scatter plot in axes (called Method1axes1):
handles.plot = scatter(X,Y, 'parent', handles.Method1axes1);
Now I want the user to be able to click the axes (plot) to get en new larger figure. I tried the below code which is working if i DON'T plot in the axes first. As soon as I run the plot function the scatterplot appears in Method1axes1 but I can no longer click the figure.
% --- Executes on mouse press over axes background.
function Method1axes1_ButtonDownFcn(hObject, eventdata, handles)
figure
scatter(X,Y);
What am I doing wrong?
This is a kind of special case for MATLAB, and it is not extremely well documented.
There are 2 things you need to consider:
1) The most obvious part. When you plot something in your axes
, the plot is on the foreground. So when you click on your axes
, the top plot intercept that click and tries to process it. You need to disable the mouse click capture from the plot/scatter/image objects you have in your axes
. For that, you have to set the HitTest
property of your scatter object to 'off'
. (recent MATLAB version have changed the name of this property, it is now called PickableParts
).
2) Much less obvious and documented. It used to be in the doc for the axes
ButtonDownFcn
callback but it is not explained anymore (although the behaviour persist). This is what I could find on old forums:
When you call PLOT, if the axes
NextPlot
property is set to'replace'
(which it is by default) most of the properties of theaxes
(includingButtonDownFcn
) are reset to their default values.Change the
axes
NextPlot
property to'replacechildren'
to avoid this, or set theButtonDownFcn
after calling PLOT, or use the low-level LINE function instead of the higher-level PLOT function.
This is also discussed and explained here: Why does the ButtonDownFcn callback of my axes object stop working after plotting something?
For your case, I tried set(axe_handle,'NextPlot','replacechildren')
and it works ok to let the mouse click reach the ButtonDownFcn
, but unfortunately it creates havoc with the axes
limits and LimitModes ... so I opted for the second solution, which is to redefine the callback for ButtonDownFcn
after every plot in the axes
.
So in summary, your code for the pushbutton1_Callback
should be:
function pushbutton1_Callback(hObject, eventdata, handles)
% Whatever stuff you do before plotting
% ...
% Plot your data
handles.plot = scatter(X,Y, 'parent', handles.Method1axes1);
% Disable mouse click events for the "scatterplot" object
set(handles.plot,'HitTest','off') ;
% re-set the "ButtonDownFcn" callback
set(handles.Method1axes1,'ButtonDownFcn',@(s,e) Method1axes1_ButtonDownFcn(s,e,handles) )
And for your axes
mouse click event, you might as well keep the handle of the new generated objects:
function Method1axes1_ButtonDownFcn(hObject, eventdata, handles)
handles.newfig = figure ;
handles.axes1copy = copyobj( handles.Method1axes1 , handles.newfig ) ;
Note that instead of plotting a new set, I simply use the copyobj
function, very handy when you need to reproduce a plot.
Illustration: