Legend ItemHitFcn with multiple functionality using left- and right-mouse buttons

6 views (last 30 days)
I use the legend ItemHitFcn frequently to toggle visiblity of specific lines, but would like to add a context menu to the legend that would allow the user to delete the selected plot item. Per the online help documentation for legend properties, it seems that the ItemHitFcn property has the ability to do this, but it not clear to me how to implement this in the code.
Ideally, the user would be able to toggle visibility with the left mouse button and open the context menu with the right mouse button (able to get this far) to delete the target (failing thus far).
I would guess that it has to do with how I have been trying to assign the context menu. Sample section of my code are provided below.
Function to toggle visibilty:
function LineVisible(~, event)
%LINEVISIBLE toggles visibility of lines in plots by selecting from legend.
% % Rough example of adding item deletion code
% if strcmp(event.SelectionType,"alt")
% delete(event.Peer)
% return
% end
% Checks the current visibility setting of the source plot line and switches to the opposite state.
if strcmp(event.Peer.Visible,'on')
event.Peer.Visible = 'off';
else
event.Peer.Visible = 'on';
end
end
Generic plot with assignment of LineVisible to the legend ItemHitFcn.
% Plot setup with ItemHitFcn assignment for line visibilty
x = linspace(0,10);
y1 = sin(x); y2 = cos(x); y3 = sin(x)+cos(x); y4 = sin(x).*cos(x);
hFig = figure;
plot(x,y1,x,y2,x,y3,x,y4)
hLeg = legend('Line 1','Line 2','Line 3','Line 4');
hLeg.ItemHitFcn = @LineVisible;
Creating the context menu and assigning to the ItemHitFcn
%% Initialize context menu object
hCM = uicontextmenu(hFig);
%% Create context menu item that will call the legend's ItemHitFcn
% Tries to assign as context menu's ItemHitFcn, which does not exist
m1 = uimenu(hCM,"Text","Delete Item","MenuSelectedFcn",@ItemHitFcn);
% No apparent effect when menu item is selected.
m2 = uimenu(hCM,"Text","Delete Item");
% Calls @LineVisible, but does not use ItemHitFcn to indicate the Peer
% object for deletion
m3 = uimenu(hCM,"Text","Delete Item","MenuSelectedFcn",@LineVisible);
% Error using @(hLeg)ItemHitFcn(hLeg)
m4 = uimenu(hCM,"Text","Delete Item","MenuSelectedFcn",@(hLeg)ItemHitFcn(hLeg));
%% Assgin object to legend ContextMenu property
hLeg.ContextMenu = hCM;

Accepted Answer

Allen
Allen on 10 May 2022
Edited: Allen on 10 May 2022
Simple detail overlooked in the legend ItemHitFcn callback documentation.
  • 'alt' — Single-click right mouse button, both mouse buttons (Windows and Mac), or middle mouse button (Mac and Linux). If the ContextMenu property contains a valid context menu (which is the default), then this type of click opens the context menu instead of triggering the ItemHitFcn callback.
Setting the ContextMenu property equal to an empty array value allows the ItemHitFcn to behave as anticipated on right mouse button use.
% Setup test plot with legend
x = linspace(0,10);
y1 = sin(x); y2 = cos(x); y3 = sin(x)+cos(x); y4 = sin(x).*cos(x);
hFig = figure;
plot(x,y1,x,y2,x,y3,x,y4)
hLeg = legend('Line 1','Line 2','Line 3','Line 4');
% Assign callback function
hLeg.ItemHitFcn = @LineVisible;
hLeg.ContextMenu = [];
% or
% set(hLeg,'ItemHitFcn',@LineVisible,'ContextMenu',[])
Code for toggling line visibility with left mouse button and opening a context menu for line deletion.
function LineVisible(src, event)
%LINEVISIBLE toggles visibility of lines in plots by selecting from legend
%or delete unwanted items.
% Determine which mouse button was used to activate the ItemHitFcn callback
% for the legend
if strcmp(event.SelectionType,'normal')
% Checks the current visibility setting of the source plot line and
% switches to the opposite state
if strcmp(event.Peer.Visible,'on')
event.Peer.Visible = 'off';
else
event.Peer.Visible = 'on';
end
elseif strcmp(event.SelectionType,'alt')
% Creates a context menu, which will be initiated immediately after
% this function completes execution
hCM = uicontextmenu(gcf);
uimenu(hCM,'Text','Delete Item','MenuSelectedFcn',{@DeleteItem,event});
src.ContextMenu = hCM;
end
end
%%
function DeleteItem(~, ~, hItem)
% Deletes the target item & resets the legend's ContextMenu property
delete(hItem.Peer)
hItem.Source.ContextMenu = [];
end

More Answers (0)

Community Treasure Hunt

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

Start Hunting!

Translated by