Thread Subject: Interaction of graphics object properties EraseMode and Visibility

Subject: Interaction of graphics object properties EraseMode and Visibility

From: Ryan Ollos

Date: 3 Dec, 2008 02:37:02

Message: 1 of 3

I have a GUI with two overlaid "pages". On one page is a sweeping display that displays data in real time, and on the other page is a set of edit uicontrols for user data entry. The parent for the sweeping display axes is a uipanel, and the parent for the uicontrols is another uipanel. The uipanels are coincident, and a togglebutton determines which will be displayed. I display one and hide the other by setting the uipanel's visibillity property to On and Off, respectively.

The sweeping display is an axes with a hundreds of image objects oriented vertically. Each image represents a column of data (i.e. a vertical line) in the display. I can then update the CData of a single column during each step of the sweep, rather than refreshing a single image that occupies the entire axes (which is an operation that is too slow to generate smooth updates at a good framerate).

So, the object heircharcy looks like this:
figure
    uipanel1
        axes
            image
    uipanel2
        uicontrol

In order to get the sweeping display to update quickly, I need to set the EraseMode property of the image objects to none. This works well because the object never needs to be erased ... during a refresh of that line the CData is updated.

The problem is that with EraseMode = 'none', the image objects are visible even when the ancestor uipanel is set to Visible = 'off'. They are not immediately visible when I hide the panel, but become visible as their CData is updated.

The net effect is that the vertical lines of the sweeping display are drawn over the top of the data input uicontrols. I can fix this by setting EraseMode = 'normal', but then the display updates much more slowly. EraseModes 'xor' and 'background' have the same problem as 'none'.

Is this a bug, or expected behavior? My renderer is 'painters'.

One of the questions I have is whether I should be updating the CData of the images when they are not visible. I had thought this would not be a problem since nothing should be rendered when the object is invisible, even if the CData is updated, right?. The problem with not updating them when they are not visible is that I would need to keep a separate buffer and update all the lines each time the sweeping display is made visible, which I can do, but I'd like to get more insight first.

I'll see if I can create a simplifed version of the GUI that shows this behavior, and post that.

Subject: Interaction of graphics object properties EraseMode and Visibility

From: Ryan Ollos

Date: 3 Dec, 2008 08:01:04

Message: 2 of 3

Here is an example of what I described above.


function h = sweeping_display_nxImages_multiPanels
% This is an example of a sweeping display that can be "hidden" by changing
% the state of a togglebutton.
%
% The sweeping display is an axes with nx vertical lines (image handle
% graphics objects). The vertical lines are updated as the sweep bar
% passes across the display. The nx vertical lines can be updated
% indepdently, and only two are updated on each step of the sweep. This
% reduces the rendering performance compared to updating two columns of
% the CData of a single image object, which causes all the data in the axes
% to be refreshed.

% The problem with this example is that the image object are drawn even
% when the visible property of their parent uipanel is 'off', when their
% EraseMode = 'none'. Setting the EraseMode = 'normal' fixes this problem,
% but the image renders more slowly and flickers.


    IMAGE_ERASEMODE = 'none';
    RENDERER = 'painters';


%% --- display parameters
% Each 'line' is actually an image handle object of width dx
    displayon = 1; % ON=1
    sweeptime = 4; % time to sweep across spectral display (s)
    Fdisp = 60; % number of lines displayed per second (Hz)
    nx = round(Fdisp*sweeptime); % number of lines in the display
    dx = 2; % width of line
    ny = 128; % number of points in the Y-direction
    nframes = 5; % number of times the display sweeps through
    % pixelsperline = 1; % display size across screen, per displayed line


%% --- Initialize the sweeping display window
    Tdisp = 1/Fdisp;
    
    % generate axes vectors of time points representing fast- and slow-time points
    X = (0:nx)*Tdisp; % times for each displayed line, on x-axis of display
    Y = 1:ny;
            
    %specimage = zeros(ny, nx); % initialize display image matrix
    specimage = repmat(ceil((1:dx*nx)/dx), [ny 1]); %each vertical line is a unique index into the colormap
    zerosline = zeros(ny, dx);
    onesline = ones(ny, dx);
       
     
    % Initialize display figure
    h.figure = figure;
    set(h.figure, 'ColorMap', colormap(gray(2)), ... %colormap(gray(nx)), ...
        'DoubleBuffer', 'on', ...
        'Renderer', RENDERER);
    
    h.uipanel1 = uipanel('Parent', h.figure, ...
        'Position', [0 0.05 1 0.95], ...
        'Visible', 'on');
    
    h.uipanel2 = uipanel('Parent', h.figure, ...
        'Position', [0 0.05 1 0.95], ...
        'Visible', 'off');
    
    h.togglebutton = uicontrol('Parent', h.figure, ...
        'Units', 'normalized', ...
        'Style', 'togglebutton', ...
        'Value', 0, ...
        'String', 'Hide Sweeping Display', ...
        'Position', [0 0 0.20 0.05]);
       
    % Initialize display axes
    CLim = [1 nx]; %index directly into colormap
    h.axes = axes('Parent', h.uipanel1, ... %'Units', 'pixels', ...
        'CLim', CLim, ...
        'XLim', [X(1) X(end)], ...
        'YLim', [Y(1) Y(end)], ...
        'XTickLabel', {''}, ...
        'YTickLabel', {''});
% Position = get(h.axes, 'Position'); %set axes size = size(CData) for direct pixel mapping
% Position(3:4) = [nx ny];
% set(h.axes, 'Position', Position);
    title (['Sweeping Diplay --- [nx ny Fdisp] ' num2str([nx ny Fdisp])])
    xlabel('Time (s)')
    ylabel('Number of points')
    colorbar;
       
       % Initialize image lines
       h.image = nan(nx, 1);
       for i=1:nx
       h.image(i) = image('XData', X(i:i+1), ...
               'YData', Y, ...
               'CData', specimage(:,i*dx-1:i*dx), ...
               'CDataMapping', 'direct', ...
               'Parent', h.axes, ...
               'EraseMode', IMAGE_ERASEMODE, ...
               'BusyAction', 'cancel');
       end
         
    set(h.togglebutton, 'Callback', {@togglePanels_Callback, h});
            
    drawnow;
            
%% Display loop
    iline = dx-1;
    Delay = nan(nframes*nx,1);
    for frame = 1:nframes
        % disp ([' *** Frame ' num2str(frame) ])
        tic
        for nn = 1:nx % line loop
            iline0 = mod(iline,dx*nx)+1; % current display line, with wrap around
            iline1 = mod(iline-dx,dx*nx)+1; % next line (current +1)
% iline2 = mod(iline+1,nx)+1; % current+2
% iline3 = mod(iline+2,nx)+1; % current+3
% iline0 = mod(iline-2,nx)+1; % previous line (current-1)

                % add the lines to the display
            specimage(:,iline0-dx+1:iline0) = CLim(2)*onesline;
            specimage(:,iline1-dx+1:iline1) = zerosline; % position bar
% specimage(:,iline2:iline2+1) = 0.5*onesline; % dimming ahead
% specimage(:,iline3:iline3+1) = 0.3*onesline;
                %set(h,'CData',specimage) % write to display
                
                set(h.image(iline0/dx), 'CData', specimage(:,iline0-dx+1:iline0));
                set(h.image(iline1/dx), 'CData', specimage(:,iline1-dx+1:iline1));
% set(h.image(iline2), 'CData', specimage(:,iline2:iline2+1));
% set(h.image(iline3), 'CData', specimage(:,iline3:iline3+1));

                k = (frame-1)*nx+nn;
                Delay(k) = nn*Tdisp-toc; % if display is faster than the desired rate, wait
                if Delay(k)>0.001,
                    pause(Delay(k)),
                    % disp ([ num2str(Delay)] );
                end
                % disp([' Delay = ' num2str(Delay) ' Frame = ' num2str(frame) ' Line = ' num2str(iline) ])
            iline = iline + dx; % iline indexes the current line in the sweeping display
        end
   end
       
%% end Frame Loop

    figure;
    subplot(3,1,1);
    t = (1:nframes*nx)/Fdisp;
    plot(t, Delay);
    title('Time series of Delay');
    subplot(3,1,2);
    hist(Delay);
    title('Histogram of Delay');
    subplot(3,1,3);
    plot(t, cumsum(Delay));
    title('Cumulative sum of time series of Delay');
    
    fprintf(1, 'Mean Delay is %.4f\n', mean(Delay));

    
function togglePanels_Callback(hObject, eventdata, h)

if get(hObject, 'Value')
    set(h.uipanel1, 'Visible', 'off');
    set(h.uipanel2, 'Visible', 'on');
else
    set(h.uipanel1, 'Visible', 'on');
    set(h.uipanel2, 'Visible', 'off');
end


% [EOF]

Subject: Interaction of graphics object properties EraseMode and Visibility

From: Ryan Ollos

Date: 3 Dec, 2008 19:18:04

Message: 3 of 3

A fix I have found is to explicity set the Visible property on all children of the uipanel to 'off' when the uipanel's Visible property is set to 'off'.

This seems like a bug, similar to what is reported here: http://www.mathworks.com/support/bugreports/details.html?rp=308433

When the Visible property of the uipanel is set to off, then graphics object children of the uipanel are not visible, provided their CData is not being changed, but their Visible property is still 'on' when queried. This behavious also seems odd to me. For example, referring again to the object heirarchy:

figure
    uipanel1
        axes
            image
    uipanel2
        uicontrol

>> get(h.uipanel1, 'visible')
ans =
off
>> get(h.uipanel2, 'visible')
ans =
on
>> get(h.axes, 'visible')
ans =
on
>> get(h.image, 'visible')
ans =
    'on'
    'on'
    'on'
    ....
    'on'


Fortunately, their is a single line fix:

    set(h.uipanel1, 'Visible', 'off');
    set(h.uipanel2, 'Visible', 'on');
    set(findall(h.uipanel1), 'Visible', 'off'); %this is a workaround for a bug


Tags for this Thread

Everyone's Tags:

Add a New Tag:

Separated by commas
Ex.: root locus, bode

What are tags?

A tag is like a keyword or category label associated with each thread. Tags make it easier for you to find threads of interest.

Anyone can tag a thread. Tags are public and visible to everyone.

Tag Activity for This Thread
Tag Applied By Date/Time
sweeping display Ryan Ollos 3 Dec, 2008 03:05:08
visible Ryan Ollos 2 Dec, 2008 21:40:19
erasemode Ryan Ollos 2 Dec, 2008 21:40:19
gui Ryan Ollos 2 Dec, 2008 21:40:19
rssFeed for this Thread
 

MATLAB Central Terms of Use

NOTICE: Any content you submit to MATLAB Central, including personal information, is not subject to the protections which may be afforded information collected under other sections of The MathWorks, Inc. Web site. You are entirely responsible for all content that you upload, post, e-mail, transmit or otherwise make available via MATLAB Central. The MathWorks does not control the content posted by visitors to MATLAB Central and, does not guarantee the accuracy, integrity, or quality of such content. Under no circumstances will The MathWorks be liable in any way for any content not authored by The MathWorks, or any loss or damage of any kind incurred as a result of the use of any content posted, e-mailed, transmitted or otherwise made available via MATLAB Central. Read the complete Terms prior to use.

Contact us at files@mathworks.com