Reputation: 1639
I try to make a MATLAB GUI programmatically and face the problem that my slider disappears after using it. I isolated the problem to keep the code short. In this GUI I want to refresh the plotmatrix
each time the slider is used (ignore the fact that the value of the slider is completely irrelevant to my program, as mentioned before I really wanted to keep the code clean that's why I also removed this functionality). Here's the code (you have to run it as function):
function StackOverflowQuestion_GUI()
% clear memory
close all; clc;
% initialize figure
f = figure;
% create main axes
AX_main = axes('Parent',f,...
'Units','normalized','Position',[.1 .2 .8 .7]);
% create slider
uicontrol('Parent',f,...
'Style','slider','Callback',{@sliderCallback,AX_main},...
'Units','normalized','Position',[0.05 0.05 0.9 0.05]);
plotmatrix(AX_main,randn(500,3));
title('Random Plotmatrix');
end
function sliderCallback(~,~,AX_main) % callback for slider
plotmatrix(AX_main,randn(500,3));
title('Random Plotmatrix NEW');
end
Any help is appreciated! I think I misunderstood the concept of AXES. When I plot to the AXES-handle I created, why are other parts of the figure affected as well? If someone could explain to me how this graphic-handle system basically works that would be very nice too!
Upvotes: 2
Views: 289
Reputation: 12214
While daren shan's answer is correct, it's bizarre enough behavior that I was curious to see what is behind it.
Stepping through the source of plotmatrix
we can find the line that deletes our slider object:
% Create/find BigAx and make it invisible
BigAx = newplot(cax);
Nothing obvious here, what does newplot
do?
Use
newplot
at the beginning of high-level graphics code to determine which figure and axes to target for graphics output. Callingnewplot
can change the current figure and current axes. Basically, there are three options when you are drawing graphics in existing figures and axes:
Add the new graphics without changing any properties or deleting any objects.
Delete all existing objects whose handles are not hidden before drawing the new objects.
Delete all existing objects regardless of whether or not their handles are hidden, and reset most properties to their defaults before drawing the new objects (refer to the following table for specific information).
Oh...
So newplot
is deleting the slider object.
So why does hold
prevent the slider from being deleted, despite it being an axis method and not a figure method? To start, take a look at the "Algorithms" topic in the documentation:
The
hold
function sets theNextPlot
property of theAxes
orPolarAxes
object to either'add'
or'replace'
.
So hold on
sets this to 'add'
for the current axes. However, for a reason I can't currently figure out, this also sets the NextPlot
of the figure to add
as well.
We can see this with a short snippet:
f = figure('NextPlot', 'replacechildren');
ax = axes;
fprintf('NextPlot Status, base:\nFig: %s, Ax(1): %s\n\n', f.NextPlot, ax.NextPlot)
hold on
fprintf('NextPlot Status, hold on:\nFig: %s, Ax(1): %s\n\n', f.NextPlot, ax.NextPlot)
Which prints:
NextPlot Status, base:
Fig: replacechildren, Ax(1): replace
NextPlot Status, hold on:
Fig: add, Ax(1): add
Weird behavior, but I won't dwell on that.
Why does this matter? Go back to the newplot
documentation. First, newplot
reads the figure's NextPlot
property to determine what to do. By default, a figure's NextPlot
property is set to 'add'
, so it would retain all of the present graphics objects but plotmatrix
explicitly changes this:
if ~hold_state
set(fig,'NextPlot','replacechildren')
end
So newplot
goes from:
Draw to the current figure without clearing any graphics objects already present.
To:
Remove all child objects whose
HandleVisibility
property is set toon
and reset figureNextPlot
property toadd
.This clears the current figure and is equivalent to issuing the
clf
command.
Which explains why the slider disappears and why hold on
fixes the problem.
Per the documentation for newplot
we can also set the HandleVisibility
of the slider UIcontrol to save it from being destroyed:
% create slider
uicontrol('Parent',f,...
'Style','slider','Callback',{@sliderCallback,AX_main},...
'Units','normalized','Position',[0.05 0.05 0.9 0.05], ...
'HandleVisibility', 'off');
Upvotes: 6
Reputation: 1213
When you call plotmatrix
, the function completely redraws the figure,
to conserve other elements you should use hold on;
hold off;
statements:
function StackOverflowQuestion_GUI()
% clear memory
clear; close all; clc;
% initialize figure
f = figure;
% create main axes
AX_main = axes('Parent',f,...
'Units','normalized','Position',[.1 .2 .8 .7]);
% create slider
uicontrol('Parent',f,...
'Style','slider','Callback',{@sliderCallback,AX_main},...
'Units','normalized','Position',[0.05 0.05 0.9 0.05]);
plotmatrix(AX_main,randn(500,3));
title('Random Plotmatrix');
end
function sliderCallback(~,~,AX_main) % callback for slider
hold on;
plotmatrix(AX_main,randn(500,3));
hold off;
title('Random Plotmatrix NEW');
end
Upvotes: 1