How to disable uicontrol 'mouseless' interaction

조회 수: 7 (최근 30일)
Jonas
Jonas 2022년 4월 21일
편집: Jonas 2022년 5월 3일
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

채택된 답변

Jan
Jan 2022년 4월 25일
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
Jonas
Jonas 2022년 5월 3일
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 2022년 5월 3일
편집: Jonas 2022년 5월 3일
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

댓글을 달려면 로그인하십시오.

추가 답변 (1개)

Jonas
Jonas 2022년 5월 3일
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
Jonas
Jonas 2022년 5월 3일
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

댓글을 달려면 로그인하십시오.

카테고리

Help CenterFile Exchange에서 Interactive Control and Callbacks에 대해 자세히 알아보기

태그

제품


릴리스

R2021a

Community Treasure Hunt

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

Start Hunting!

Translated by