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
Jan
2017년 6월 23일
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?
Chenghao
2017년 6월 23일
Jan
2017년 6월 24일
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".
답변 (1개)
Walter Roberson
2017년 6월 23일
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
Walter Roberson
2017년 6월 24일
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)
Chenghao
2017년 6월 24일
Jan
2017년 6월 24일
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.
Walter Roberson
2017년 6월 24일
편집: Walter Roberson
2017년 6월 24일
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.
카테고리
도움말 센터 및 File Exchange에서 Creating, Deleting, and Querying Graphics Objects에 대해 자세히 알아보기
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!