Hello, I am a student new with Matlab and I am learning to work with mouse input.
My objective is to make it so that when the figure is clicked, a new shape is created,
however when an already existing shape is clicked, no new shape is created but instead the
existing one is deleted. I wrote the following code below and I am really unsure as to why the
else statement executes regardless. I can seemingly only delete the previously created shape instead of
any on the scene. I would really appreciate if you could point me in the right direction as I have
been stuck on this for a few days now.
Kindest regards!
Here is the code:
clear, clc, close all
fig = figure('color','k');
ax = axes('Position',[0 0 1 1])
hold on
axis([0 5 0 5],'off')
h = 0;
while true
waitforbuttonpress
if ~isempty(h) & gco == h
delete(h);
else
xy = get(gca,'CurrentPoint');
h = fill(xy(1,1) + rand(1,8)-0.5, xy(1,2) + rand(1,8)-0.5,
rand(1,3),'EdgeColor','w'); % The random colours
end
end

 Réponse acceptée

Geoff Hayes
Geoff Hayes le 22 Avr 2020

1 vote

Jakub - look closely at the code
if ~isempty(h) & gco == h
delete(h);
else
xy = get(gca,'CurrentPoint');
h = fill(xy(1,1) + rand(1,8)-0.5, xy(1,2) + rand(1,8)-0.5, ...
rand(1,3),'EdgeColor','w'); % The random colours
end
Since h is being used to delete the graphics object (the fill) and it assigned the last created fill object, then the only time that you can potentially delete an object is if it were just added (I think that I was able to do this once or twice in a dozen or more tries). What you really want to do is delete the object when the mouse pointer hovers over it while you press the mouse button. This can be accomplished using the hit test which determines if the object can respond to the mouse click it captures or passes the click to its closest ancestor. It seems that this property is enabled (on) by default so you just need to add a callback to the fill objects and the axes to do what you want.
function HitTestExample
close all
fig = figure;
ax = axes('Position', [0 0 1 1], 'color', 'k'); % <-- added colour to axes
hold on
axis([0 5 0 5]) % <-- removed 'off' so visible
set(fig, 'HitTest', 'off');
set(ax, 'ButtonDownFcn', @OnAxesButtonDown,'HitTest','on')
% Graphics Object (GO) button down callback
function OnGOButtonDown(hObject, eventdata)
delete(hObject);
end
% Axes button down callback
function OnAxesButtonDown(hObject, eventdata)
xy = get(hObject,'CurrentPoint');
fill(xy(1,1) + rand(1,8)-0.5, xy(1,2) + rand(1,8)-0.5,rand(1,3), ...
'EdgeColor', 'w', 'ButtonDownFcn', @OnGOButtonDown); % The random colours
end
end
We ensure that the 'HitTest' is 'on' for the axes and 'off' for the figure. When the mouse button is pressed over the axes (but not over a child of the axes), then the OnAxesButtonDown is called and a new shape is created. When the mouse button is pressed over a graphics object, then the OnGOButtonDown is called and we delete the object.

6 commentaires

Jakub Klimiuk
Jakub Klimiuk le 22 Avr 2020
Modifié(e) : Jakub Klimiuk le 22 Avr 2020
Thank you for this, it is very helpful to me and I understand where my mistake is, however do you know if there is any way of achieving this without functions and callbacks to the functions? I am currently using Octave rather than Matlab as we only have Matlab in university and I cannot access it due to Covid. Octave currently hasn't implemented callbacks to nested functions I believe. The code gives me an error.
Geoff Hayes
Geoff Hayes le 23 Avr 2020
What is the error?
This is the error when I remove the main function:
error: @OnAxesButtonDown: no function and no method found
error: called from
Part2 at line 9 column 5
error: evaluating argument list element number 3
error: called from
Part2 at line 9 column 5
>>
This is the code when I leave your code as it is and try to run:
error: handles to nested functions are not yet supported
error: called from
Part2 at line 11 column 5
error: evaluating argument list element number 3
error: called from
Part2 at line 11 column 5
>>
The nested functions aren't necessary (just convenient). Try putting all three functions in the same file as
function HitTestExample
close all
fig = figure;
ax = axes('Position', [0 0 1 1], 'color', 'k'); % <-- added colour to axes
hold on
axis([0 5 0 5]) % <-- removed 'off' so visible
set(fig, 'HitTest', 'off');
set(ax, 'ButtonDownFcn', @OnAxesButtonDown,'HitTest','on')
end
% Graphics Object (GO) button down callback
function OnGOButtonDown(hObject, eventdata)
delete(hObject);
end
% Axes button down callback
function OnAxesButtonDown(hObject, eventdata)
xy = get(hObject,'CurrentPoint');
fill(xy(1,1) + rand(1,8)-0.5, xy(1,2) + rand(1,8)-0.5,rand(1,3), ...
'EdgeColor', 'w', 'ButtonDownFcn', @OnGOButtonDown); % The random colours
end
Jakub Klimiuk
Jakub Klimiuk le 23 Avr 2020
This works perfectly, thank you tons for your time and effort helping me with this! I can finally progress with my assignment. Im gonna have a further read on this and where the eventdata actually comes from. I had no idea this could be so simple.
Geoff Hayes
Geoff Hayes le 23 Avr 2020
Glad to have been able to help, Jakub!

Connectez-vous pour commenter.

Plus de réponses (0)

Catégories

En savoir plus sur Creating, Deleting, and Querying Graphics Objects dans Centre d'aide et File Exchange

Produits

Version

R2020a

Community Treasure Hunt

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

Start Hunting!

Translated by