Error message with 'visible' when using GUI

I used a GUI which was built in an older version of MATLAB. I got the error like this when I tried to run it in Matlab 2015:
Error using matlab.graphics.Graphics/set
The name 'visible' is not an accessible property for an instance of class
'matlab.graphics.GraphicsPlaceholder'.
Error in enablews (line 20)
set(h{i}(:),'visible',state);
Error in rcmgui (line 109)
enablews(HANDLES.ws{3},'off');
The script enablews.m is
function enablews(ws,state)
% ENABLEWS(WS,STATE) change the 'visible' attribute of the handles
% contained in WS. WS is a structure of doubles, and STATE is eiter 'on'
% or 'off'.
%
% Used by PSASS
if isempty(ws)
return;
end
h = struct2cell(ws); % a cell of handles
nh = length(h);
for i=1:nh
if iscell(h{i})
set(cat(1,h{i}{:}),'visible',state);
else
set(h{i}(:),'visible',state);
end
end

3 Comments

What is your question? What exactly is the "older version of MATLAB"? The graphics engine has been changed. How has ws been created? Why does it contain a 'matlab.graphics.GraphicsPlaceholder' and not a graphics handle?
The script was written using MATLAB 2010. For ws, the command that generates it is
HANDLES.ws = cell(1,4);
Well it seems that ws is a graphics handle, right?
No, ws is create as a cell array, which contains empty double matrices. In R2010b graphic handles had the type double, such that this worked, but in modern Matlab versions, graphic handles have their own type.
A variable is not a handle, only because it is a field of a struct which is called "HANDLES".

Sign in to comment.

Answers (1)

Your code has at least one place that uses a vector of handles, in which not all elements of the vector have been assigned to. For example,
h(2) = line([1 2], [3 4]);
would create h as a vector with two elements, the second of which would be a primitive line object, but the uninitialized one would be a graphics placeholder object.
In HG1, up to and including R2014a, the unassigned locations would have a value of 0, which is the graphics root. Those earlier versions often allowed you to get away with setting the visible property of 0.
The way to test for something not being a graphics placeholder is the isgraphics() test that was added in R2014b.
This suggests:
t = h;
mask = cellfun(@iscell, t);
t(mask) = cellfun(@cell2mat, t(mask), 'uniform', false);
t = cellfun(@(L) L(:), t, 'uniform', false);
t = vertcat(t{:});
t = unique( t(isgraphics(t)) );
set(t, 'visible', state)
This code does assume that within any one nested cell that the dimensions are compatible, but your existing code assumed that too.

5 Comments

Chenghao
Chenghao on 24 Jun 2017
Edited: Chenghao on 24 Jun 2017
Hi Walter,
Thank you for your answer. I am a little bit confused... Is the code you provided only for testing purpose? Because I tried to paste the code into my function and modify all 't's to 'h's, but seems the h is converted to a non-cell array object...
Since I am not familiar with all the details inside the model, is there any way I can just assign the unassigned locations in h with value 0, without touching upon other modules?
Thanks again.
The line
t = h
is to take a copy of h in case the original is needed later; the copy is modified but the original is left alone. It is expected that the copy would be modified to eventually become just a column vector of handles, so that we can reduce down to a single set() call. This replaces all of the looping and "if" tests. The code should work as-is, I think, provided I have understood the possible inputs correctly.
"Since I am not familiar with all the details inside the model, is there any way I can just assign the unassigned locations in h with value 0, without touching upon other modules?"
It would be possible to replace all of the placeholders with 0, which would convert them to groot objects (the HG2 equivalent of the 0 root object). However, doing that would not accomplish anything useful, as these days it is not permitted to set() the visible property of 0.
Annotating:
%take a copy of h so we do not ruin the original
t = h;
%find the entries that are themselves cells
mask = cellfun(@iscell, t);
%for the entries that are cells only, convert the cells of handles
%into a vector or matrix of handles, stripping off the cell
%layer. This is equivalent to the cat(1) that you are doing
%but in a vectorized form.
t(mask) = cellfun(@cell2mat, t(mask), 'uniform', false);
%now all of the entries are vectors or arrays of cells. But
%we do not know their size or orientation and we are not
%promised that those are consistent. So run through them
%and make them all column vectors.
t = cellfun(@(L) L(:), t, 'uniform', false);
%now we can make it into one big column vector and do
%not need the cell form any more
t = vertcat(t{:});
%now that we have one big column vector, we can do a
%vectorized test as to whether each handle is an
%active handle. This was originally put in to test for
%items that had not been assigned to, but it has the bonus
%of getting rid of the items that hold handles to deleted
%entries. The result of isgraphics(t) is a logical mask,
%and we can index t at that mask to get just the valid values.
%Oh, and since we are here, let's reduce down to the unique
%handles just in case there were duplicates.
t = unique( t(isgraphics(t)) );
%we now have a column vector of unique handles of valid
%objects. We can set their state all at the same time.
set(t, 'visible', state)
Thank you so much! I followed your instruction and now I can open the interface. But it seems that I cannot load any files to my interface (some features of the interface do not function)...
When I tried to click the button on the interface, I got error like:
Undefined function 'nonzeros' for input arguments of type 'matlab.graphics.axis.Axes'.
Error in cbfun>clearfig (line 2665)
htmp = allchild(nonzeros(HANDLES.hplt));
Error in cbfun (line 572)
[HANDLES,WSPARM]=clearfig(HANDLES,WSPARM);
Error while evaluating UIControl Callback
The line 2665 is for deleting existing plots and their children.
Do you think this is still related to my previous problem?
Thank you!
It is still the same problem: "nonzeros" removes all zero values from the input, but in modern Matlab versions graphic handles are not doubles anymore. Therefore they cannot be zero at all. The code needs a substantial re-design to consider the new HG2 graphics system. Unfortunately the current version mixes handles and numbers, which was working in older Matlab versions, but it was not clean, as you can see now.
Change
htmp = allchild(nonzeros(HANDLES.hplt));
to
temp = HANDLES.hplt;
temp = temp( isgraphics(temp) );
htmp = allchild(temp);
That will get you through to the next place that assumes that handles are numeric.
Whatever code you are using does not appear to be indexed by Google, so I cannot glance at it to guess at how much more work is needed.

Sign in to comment.

Categories

Find more on Creating, Deleting, and Querying Graphics Objects in Help Center and File Exchange

Asked:

on 23 Jun 2017

Edited:

on 24 Jun 2017

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!