How to disable uicontrol 'mouseless' interaction

7 Ansichten (letzte 30 Tage)
Jonas
Jonas am 21 Apr. 2022
Bearbeitet: Jonas am 3 Mai 2022
Dear community,
at the moment I'm creating a gui using normal figures and uicontrol elements. One side is a plotting window in which the user can interact using key press and mouse klick, the other half of the figure are some additional settings like visibility of certain elements etc using checkboxes for example
If I click on a checkbox and afterwards i press 'space' in the plotting window which is processed by ''WindowButtonDownFcn''.
My Problem is, that at the same time the 'space' changes the checkbox value
Similar things happen if I changed the value of a popupmenu and I want to navigate in the plotting window using the arrow keys.
The Callbacks of the 'WindowButtonDownFcn' are processed correctly, but at the same time i change the value of the uicontrol
How can I remove this behavior such that the user can not interact with uicontrol elements using keyboard button press (and also navigating using TAB once an uicontrol element was used) but only mouse clicks
I am using Win10 and Matlab 2021a
here a short "working" example
close all;
fig=figure;
% create plots and disable interactivity
s=subplot(1,2,1);
p=plot(rand(1,1000));
axtoolbar(s,'Visible','off');
disableDefaultInteractivity(s);
%% create buttons and set window key press function
pressedButton= uicontrol(fig,'Style','text');
pressedButton.Units='normalized';
pressedButton.Position = [0.7 0.7 0.2 0.04];
pressedButton.String = 'no key pressed yet';
fig.WindowKeyPressFcn=@(~,ev) set(pressedButton,'String',ev.Key);
colorPopup = uicontrol(fig,'Style','popupmenu');
colorPopup.Units='normalized';
colorPopup.Position = [0.7 0.5 0.2 0.04];
colorPopup.String = {'r','b','k','c'};
colorPopup.Value = 1;
colorPopup.Callback =@(~,~) set(p,'Color',colorPopup.String{colorPopup.Value});
visibilityCheckbox = uicontrol(fig,'Style','checkbox');
visibilityCheckbox.Units='normalized';
visibilityCheckbox.Position = [0.7 0.6 0.2 0.04];
visibilityCheckbox.String='Visibility';
visibilityCheckbox.Value=1;
visibilityCheckbox.Callback=@(~,~) set(p,'Visible',visibilityCheckbox.Value);
best regards
Jonas

Akzeptierte Antwort

Jan
Jan am 25 Apr. 2022
If you click on an uicontrol element, it gets the focus. Then following keyboard events are caught be the keyboard handling of the uicontrol. A solution is to give the focus back to the figure or the axes in the callback of the uicontrol. This should work by figure(fighandle) according to the documentation, but this was not successful at least for Matlab 6.5 to 2018b (the newest version I have).
Workarounds:
  • Insert code in the callbacks, which sets the "Enable" property of the uicontrol to 'off' temporarily:
function checkBoxCallback(ObjH, EventData)
set(ObjH, 'Enable', 'off');
drawnow;
set(ObjH, 'Enable', 'on');
pause(0.02); % Voodoo!
end
WindowAPI(figHandle, 'setFocus')
  10 Kommentare
Jonas
Jonas am 3 Mai 2022
long question, short answer: the java objects have a focusable attribute which can be set to 0 and solve all the problems, no need for any listeners or callbacks. I just added the following after creation of all uicontrol elements
objs=findall(fig,'type','uicontrol'); % get the uicontrol elements
for nr=1:numel(objs)
jobj=findjobj(objs(nr),'persist'); % findjobj can hadnle only one obj at a time, the persistent argument speeds up the finding process of jobj
jobj.Focusable=false;
end
% instead of the for loop we could also use
% arrayfun(@(in) set(findjobj(in,'persist'),'Focusable',false),objs)
thanks again to @Jan for his help!
Jonas
Jonas am 3 Mai 2022
Bearbeitet: Jonas am 3 Mai 2022
and another comment: i don't know why, but we can't set the Focusable attribute, if the UIControl element is Invisible and it seems to reset it's proeprty when made visible. for that reason i used @Jan's solution with the Release callback
Jan included an HList Object, but there was no such object available and i was too dumb to get the Matlab handle from the java jPopH handle
uiButtons=findall(fig,'type','uicontrol');
for count=1:numel(uiButtons)
if uiButtons(count).Visible
jobj=findjobj(uiButtons(count));
jobj.MouseReleasedCallback=@(H, E) KillFocus(uiButtons(count));
end
end
function KillFocus(obj)
set(obj, 'Enable', 'off');
drawnow;
set(obj, 'Enable', 'on');
end

Melden Sie sich an, um zu kommentieren.

Weitere Antworten (1)

Jonas
Jonas am 3 Mai 2022
for better visiblity here the last state of our discussion. thanks @Jan!
long question, short answer: the java objects have a focusable attribute which can be set to 0 and solve all the problems, no need for any listeners or callbacks. I just added the following after creation of all uicontrol elements
objs=findall(fig,'type','uicontrol'); % get the uicontrol elements
for nr=1:numel(objs)
jobj=findjobj(objs(nr),'persist'); % findjobj can hadnle only one obj at a time, the persistent argument speeds up the finding process of jobj
jobj.Focusable=false;
end
% instead of the for loop we could also use
% arrayfun(@(in) set(findjobj(in,'persist'),'Focusable',false),objs)
thanks again to @Jan for his help!
  1 Kommentar
Jonas
Jonas am 3 Mai 2022
and another comment: i don't know why, but we can't set the Focusable attribute, if the UIControl element is Invisible and it seems to reset it's proeprty when made visible. for that reason i used @Jan's solution with the Release callback
uiButtons=findall(fig,'type','uicontrol');
for count=1:numel(uiButtons)
if uiButtons(count).Visible
jobj=findjobj(uiButtons(count));
jobj.MouseReleasedCallback=@(H, E) KillFocus(uiButtons(count));
end
end
function KillFocus(obj)
set(obj, 'Enable', 'off');
drawnow;
set(obj, 'Enable', 'on');
end

Melden Sie sich an, um zu kommentieren.

Kategorien

Mehr zu Interactive Control and Callbacks finden Sie in Help Center und File Exchange

Produkte


Version

R2021a

Community Treasure Hunt

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

Start Hunting!

Translated by