Editing impoly polygons in a GUIDE app
現在この質問をフォロー中です
- フォローしているコンテンツ フィードに更新が表示されます。
- コミュニケーション基本設定に応じて電子メールを受け取ることができます。
エラーが発生しました
ページに変更が加えられたため、アクションを完了できません。ページを再度読み込み、更新された状態を確認してください。
古いコメントを表示
In a GUIDE app, I want to draw polygons on an image (say 4 polygons), then copy the polygons and display on a different image, then edit those polygons and save the changes with the new image. AFAIK, I need to use impoly because I have R2017b. I click a button on the GUI, which runs a function where I use h = impoly. I am experimenting with addNewPositionCallback inside this function, but after this function has executed, I don't see any way to get to that polygon again to detect changes. When I display a particular image, I want to draw the polygons associated with that image (not a problem), but the problem comes when I want to detect edits that the user can then make to the polygons associated with that image. Any examples of doing this would be appreciated. Again, I don't have a problem storing polygons and drawing them later, the problem is editing them and saving the changes.
Thanks
Ron
1 件のコメント
I have a function that is called when a user clicks a button on the GUI:
function handles = draw_polygon(handles)
h = impoly; %allow user to draw polygon
fcn = @posChanged;
addNewPositionCallback(h, fcn);
points = h.getPosition;
...
end
function posChanged(pos)
pos %write out for testing
end
posChanged gets called when I move vertices of the polygon, but I cannot save the changes because I do not have access to handles in posChanged. Is there a way to pass handles into posChanged? handles is essentially a place where I store "global" variables in the GUI app.
Ron
採用された回答
Adam Danz
2019 年 8 月 23 日
"after this function has executed, I don't see any way to get to that polygon again to detect changes"
Once the callback function is finished, all variable values within the function are lost forever unless you save them (exceptions are global and persistant variables which are not recommended).
You can use guidata() to save variables to your GUI so when you enter a callback function, those values can be retreived. Here's a demo that stores/retreives data in/from the GUI figure itself but you could chose any GUI object.
function myCallbackFunction(hObject, event, handles)
h = impoly(. . .);
dat = guidata(handles.figure); %assuming the handle to your figure is named 'figure'
if ~isfield(dat,'PolyHandles')
% add the field if it doesn't exist already
dat.PolyHandles = [];
end
dat.PolyHandles(end+1) = h; %add new handle to end
guidata(handles.figure,dat); %store the updated data
end
To clear the handles,
dat = guidata(handles.figure);
dat.PolyHandles = [];
guidata(handles.figure,dat);
Once you have the handles, you can do everything in your question: edit them, copy them to another image, etc.
14 件のコメント
RonE
2019 年 8 月 23 日
Thanks Adam, but I think this can be done more simply. Here is what I have for lots of functions. I guess it's one line simpler. handles is already passed into the function so no need to retrieve anything.
function myCallbackFunction(hObject, event, handles)
h = impoly(. . .);
%dat = guidata(handles.figure); %assuming the handle to your figure is named 'figure'
if ~isfield(handles, 'PolyHandles')
% add the field if it doesn't exist already
handles.PolyHandles = [];
end
handles.PolyHandles(end+1) = h; %add new handle to end
guidata(hObject, handles); %store the updated data
end
I tried storing the handle to an impoly in handles, but when I tried to use it later, Matlab said the handle to my impoly has been deleted. It was still there but apparently empty. I assume because it was no longer displayed on the figure. It seems I will have to store the polygon shape, then redraw it and get a new handle. But my big problem is still capturing user edits to the polygon.
It looks like you applied my answer to the handles structure which is a fine choice.
"Matlab said the handle to my impoly has been deleted. "
The handle and the object are two different things. You can have an object and delete the handle. And you can have a handle and delete the object but the handles becomes virtually useless.
"It seems I will have to store the polygon shape, then redraw it and get a new handle. "
Maybe that could be a solution but there might be a better one depending on your goals. Why are the polygons being deleted? How are they being deleted? Why do they need to come back into existance? If I get a better idea of what you're doing I might be able to make some suggestions. For example, you can turn off/on the visibility of an object without deleting/recreating it.
RonE
2019 年 8 月 26 日
Adam, Thank you for the response. I will try to explain. I have several images (frames) that can be displayed, each with its own set of polygons. I want the user to be able to draw and edit the polygons associated with each image. I have it working where I can draw polygons, save them, and draw them later on the correct image. (When I say the polygons are 'deleted', they must no longer be drawn when I move to a different image.) My problem is that I would like to be able to move vertices, add vertices, drag, etc the polygons on each image and save the changes. Don't know how to do this. I have managed to get a function to be called using addNewPositionCallback as I described above, but the only parameters my function posChanged takes is the updated points of the polygon, so I don't have enough info to save the updated polygon. I don't know which image frame it is associated with. Ideally I would like to have my posChanged function receive the polygon points (pos) and 'handles' from the GUI. Or just pass it any parameter other than the points.
Ron
" Ideally I would like to have my posChanged function receive the polygon points (pos) and 'handles' from the GUI. Or just pass it any parameter other than the points."
Isn't the first input to the addnewpositioncallback() function the polygon handle? You could pass the handle into the addNewPositionCallback function and then pass it again into your response function.
addNewPositionCallback(h,@(p) newPosFcn(p,h));
function newPosFcn(p,h)
% h is the handle to your object.
% p is its position
end
RonE
2019 年 8 月 26 日
"Isn't the first input to the addnewpositioncallback() function the polygon handle? If you pass the handle into that function (which, I believe is input #1) then you can get the point positions."
Yes:
h = impoly; %allow user to draw polygon
fcn = @posChanged;
addNewPositionCallback(h, fcn);
But posChanged receives one paramter. I don't know what goes on behind the scenes to specify this. I can pass something different than the updated polygon points into posChanged, by changing the middle line to fcn = @posChanged(handles) for example, but that is still only one paramter. I need two. Maybe the updated polygon points are inside handles somewhere, but I don't see them.
Ron
Pass the object handle into the addNewPositionCallback function. Then you can use object functions to pull info out of the object handle.
Here's a list of object function that may be helpful.
also see
methods impoly %Run this line to produce the results below
Methods for class impoly:
addNewPositionCallback getPosition resume setPosition
createMask getPositionConstraintFcn setClosed setPositionConstraintFcn
delete impoly setColor setVerticesDraggable
getColor removeNewPositionCallback setConstrainedPosition wait
Here's a demo that pulls out the (x,y) coordinates of the vertices.
addNewPositionCallback(h,@(p) newPosFcn(p,h));
function newPosFcn(p,h)
verts = getPosition(h)
end
RonE
2019 年 8 月 26 日
Think I may have found the missing link:
h = impoly;
fcn = @(a, b) posChanged(handles, h);
addNewPositionCallback(h, fcn);
...
posChanged(handles, h)
h.getPosition %Get updated polygon vertices
%Assign to structure in handles, etc.
end
This should work for me. New discoveries are often made the first few minutes after starting to work in the morning.
Adam Danz
2019 年 8 月 26 日
Ha! See my comment above. :)
RonE
2019 年 8 月 26 日
Yes it's the same thing, huh? Why does it not seem to matter what is in the "arglist", the p in fcn = @(p) newPosFcn(p,h) ? I can use p or p,q for example and the program functions the same. Why does there not need to be 2 arguments there?
Ron
First, congrats on solving this prior to seeing my comment. People always learn more when they solve it on their own and those 'ah-ha' moments make lasting changes in the brain.
To address your question, anonymous functions define an expression and its inputs but they also can store additional pre-existing variables that the expression requires for evaluation.
Check out Matlab's explanation for more detail.
RonE
2019 年 8 月 26 日
When we create a callback function associated with an impoly handle like this, how long does the connection to the function exist? As long as the handle exists or what? Even if the handle were saved in a mat file? Or can the function connect to only one polygon at a time?
Ron
Yes, as long as the handle exists. Think of it this way. When you assign the addNewpositionCallback function to a handle, that function and all of its inputs are stored as a property of that handle. When the function is called, it invokes the function using the inputs stored within the handle's addNewPositionCallback function.
If you save the handle to a mat file, clear your workspace, and then load the handle back in, it should behave in the same way even if other imploy objects have similar callback functions.
You could test that, of course.
RonE
2019 年 8 月 26 日
It looks like I have it working pretty well, although I need to redraw the frame when the user stops editing (dragging a vertex, etc). Thanks for your help. I don't know how to detect when the user stops editing. Maybe I would have to use a timer. You have a any idea?
Adam Danz
2019 年 8 月 26 日
Maybe you could add a button to your figure. After the fig is created, this line below will add a button to the bottom, left corner.
uicontrol('style','pushbutton','Units','normalize','position',[.05,.05,.08,.05],'String','Done','Callback',@yourfunc)
You'll need to write a sensible callback function that sets some kind of flag to signal the editing is done to execute the next steps.
その他の回答 (0 件)
カテゴリ
ヘルプ センター および File Exchange で Interactive Control and Callbacks についてさらに検索
参考
Web サイトの選択
Web サイトを選択すると、翻訳されたコンテンツにアクセスし、地域のイベントやサービスを確認できます。現在の位置情報に基づき、次のサイトの選択を推奨します:
また、以下のリストから Web サイトを選択することもできます。
最適なサイトパフォーマンスの取得方法
中国のサイト (中国語または英語) を選択することで、最適なサイトパフォーマンスが得られます。その他の国の MathWorks のサイトは、お客様の地域からのアクセスが最適化されていません。
南北アメリカ
- América Latina (Español)
- Canada (English)
- United States (English)
ヨーロッパ
- Belgium (English)
- Denmark (English)
- Deutschland (Deutsch)
- España (Español)
- Finland (English)
- France (Français)
- Ireland (English)
- Italia (Italiano)
- Luxembourg (English)
- Netherlands (English)
- Norway (English)
- Österreich (Deutsch)
- Portugal (English)
- Sweden (English)
- Switzerland
- United Kingdom (English)
