dcts
dcts

Reputation: 1639

Slider disappears from GUI after being used

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

Answers (2)

sco1
sco1

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. Calling newplot 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 the NextPlot property of the Axes or PolarAxes 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 to on and reset figure NextPlot property to add.

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

Hadi
Hadi

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

Related Questions