Updating handles from within Position Changed Callback

1 次查看(过去 30 天)
I have defined an impoint roi object inside of an axis. I've set up the impoint with a callback for position changed function, and in that function I change the position of a second impoint as follows:
function positionChanged(pos)
handles = guihandles;
pointMoved = gco; %moving point is currently selected object
...
kids = get(pointMoved,'Children');
kids2 = get(correspondingPoint,'Children');
set(kids2(1),'Position',get(kids(1),'Position'));
set(kids2(1),'String',get(kids(1),'String'));
set(kids2(2),'XData',get(kids(2),'XData'));
set(kids2(2),'YData',get(kids(2),'YData'));
set(kids2(3),'XData',get(kids(3),'XData'));
set(kids2(3),'YData',get(kids(3),'YData'));
I'm just trying to get correspondingPoint to have the same values and positions as the point generating the callback, and the above works pretty well for this. The problem is that upon moving or resizing my figure window, all of those set values (minus the 'String' property, for some reason) revert, and my second impoint goes back to the position it had before the callback.
  2 个评论
Sean de Wolski
Sean de Wolski 2014-7-15
My guess is that it's the gco. Can you get the handle from somewhere else?
Stephen
Stephen 2014-7-16
Hrm... now that I think about it you may be right, but I am not sure how I would go about getting that another way. I have an arbitrary number of points defined at runtime, so each of them would execute the same callback. The way MATLAB handles the interrupt I have no way of controlling the input arguments to see which point is responsible for the callback. Anyone have any ideas?

请先登录,再进行评论。

采纳的回答

Alfonso Nieto-Castanon
Your figure might have a resizefcn callback that could be reverting those values. Check:
get(gcf,'resizefcn');
  7 个评论
Alfonso Nieto-Castanon
编辑:Alfonso Nieto-Castanon 2014-7-17
I would do something like this:
f = impoint(gca,handles.lastPoint{1},handles.lastPoint{2});
setColor(f,color);
pos = getPosition(f);
setString(f,[num2str(pos(1)) ', ' num2str(pos(2))]);
%duplicate on the filtered axis
f2 = impoint(handles.axFiltered,handles.lastPoint{1},handles.lastPoint{2});
setColor(f2,color);
pos2 = getPosition(f2);
setString(f2,[num2str(pos2(1)) ', ' num2str(pos(2))]);
%ensure string gets updated if user interactively moves point
addNewPositionCallback(f,@(varargin)positionChanged(f,f2));
addNewPositionCallback(f2,@(varargin)positionChanged(f2,f));
The last two lines are the ones being modified. I am using that syntax to pass the impoint objects to the positionChanged function. Then you could have the function positionChanged something like:
function positionChanged(f1,f2)
pos=getPosition(f1);
setPosition(f2,pos);
end
And that will keep both impoint object positions "locked". Also note that if you have many impoint objects that want similarly locked (in pairs), you can just have one single positionChanged function that serves all of these, and define during the addNewPositionCallback call the appropriate parameters to pass to this function for each pair of impoint objects. Does this make sense?
Stephen
Stephen 2014-7-17
编辑:Stephen 2014-7-17
Yes, that makes sense and works well! I tried it out on a copy of my code, and seems to do it. That's a neat trick to be able to cast varargin. Much appreciated! I was also able to hack my way through the problem as in the answer below, but this is much simpler.

请先登录,再进行评论。

更多回答(1 个)

Stephen
Stephen 2014-7-17
While I did not solve the problem, I did come up with a work-around which does what I need, in case anyone comes after me has the same issues. I've found that if you first change the position of an impoint object inside of the callback as done in the original question, and then go through and create new impoint objects in their place, the changed position is stable so long as you're careful to keep the handles.impoint array updated. Here is the code inside of the position changed callback which does that, by iterating through the handles.impoints array:
handles = guihandles;
for i = 1:length(handles.impoint)
currentPoint = handles.impoint(i);
kids = get(currentPoint,'children');
%save everything to put into new point
x = get(kids(3),'XData');
y = get(kids(3),'YData');
string = get(kids(1),'String');
axis = get(currentPoint,'parent');
userData = get(currentPoint,'UserData');
color = get(currentPoint,'children');
color = get(color(2),'Color');
%don't overwrite the currently moving point
if i == pointMovedIdx
continue;
end
%otherwise, remake the point
h = impoint(axis,x,y);
setString(h,string);
setColor(h,color);
%add the correct callback based on which axis it's in
if axis == handles.axFiltered
%it's in axFiltered
addNewPositionCallback(h,@positionChangedFiltered);
%get the double handle
han = get(handles.axFiltered,'children');
han = han(1);
else
%it's in axUnfiltered
addNewPositionCallback(h,@positionChangedUnfiltered);
han = get(handles.axUnfiltered,'children');
han = han(1);
end
set(han,'UserData',userData);
handles.impoint(i) = han;
delete(currentPoint);
end

类别

Help CenterFile Exchange 中查找有关 Just for fun 的更多信息

标签

Community Treasure Hunt

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

Start Hunting!

Translated by