WindowKeyPressFcn stops being called - matlab

I am working on some modifications to EEGlab's eegplot function (things like vim-style navigation etc.) that need to work through WindowKeyPressFcn.
However, the callback is not being called for some reason. I have been debugging the issue for some time and am a bit lost. I am looking for suggestions on what might be wrong. Unfortunatelly the eegplot function is big, complex and somewhat convoluted and I was unable to reproduce the issue in a simple example. Therefore I am looking for general suggestions on why a function handle that is clearly present in WindowKeyPressFcn might stop being used at some point.
Here is what I have learned so far:
If I go to debug mode in eegplot (set a breakpoint near the end of the setup function [the first half of eegplot]) I am able to run the WindowKeyPressFcn at least once.
However - the function stops being called at some point during debug (sometimes even after being called only once).
If I run eegplot without debug (that is wait for it to finish and return control to me) I am unable to call WindowKeyPressFcn by pressing a key. The function handle is still present in WindowKeyPressFcn property of the figure.
Whener the WindowKeyPressFcn is not being used when I press a key, I can still call it with:
figh = gcf;
fun = get(figh, 'WindowKeyPressFcn');
ev.Key = 'rightarrow';
ev.Character = ' ';
ev.Modifier = [];
feval(fun, figh, ev);
So the function handle is 'healthy' so to speak, but for some reason it is not being used any more when a key is pressed and the figure has focus. When and why something like this could happen? Any ideas on things I should check to understand this issue?
Update:
I found out that WindowKeyPressFcn callback can sometimes be blocked by some window listeners, and tried out the following solution:
hManager = uigetmodemanager(gcf);
set(hManager.WindowListenerHandles,'Enable','off');
It doesn't work - WindowKeyPressFcn is still not called when I press a key. :(
Update 2:
Another thing that does not work:
chld = get(gcf, 'Children');
tp = get(chld, 'type');
chld = chld(strcmp(tp, 'uicontrol'));
set(chld, 'KeyPressFcn', #eegplot_readkey_new)
(eegplot_readkey_new is the function I use for reacting to keypresses)
Update 3:
And another one not working:
addlistener(gcf, 'WindowKeyPress', #eegplot_readkey_new);

Ok - I fiugred it out, although the solution is weird to say the least.
For some mysterious reason using linesmoothing undocummented property prevents WindowKeyPressFcn from being called. I have absolutely no idea why...

Related

unexpected frame appears onto another frame after an event

I'm using a character application. In the first page, there is a frame f-selection where the search fields are entered. When I search for something and open some other frames in that search, then I press F10 which is for opening another frame, the new frame opens but f-selection also appears on it. I'm suspecting this code makes it pop up again:
else assign ll-lgst-key1:SENSITIVE in frame f-selection = TRUE
ll-lgst-key2:SENSITIVE in frame f-selection = FALSE
because when I comment these lines, the frame doesn't pop up. But then I can't use these fields at the first frame where I should, too. I don't know why this code is called again; but is there anything else I can do to fix this issue? I tried to write hide frame f-selection everywhere possible but it doesn't work.
That snippet of code is making "key1" of your frame sensitive. In order to be sensitive it needs to pop up...
So the issue is why is that block of code executing? You say "I don't know why this code is called again". Neither will anyone else because you have shared such a tiny little bit of the overall code. Apparently the flow of control is taking you through that block so you should work on understanding why that is. You might try using the debugger to step through the code execution or you could insert some old fashioned MESSAGE statements to get to the bottom of it.
If you want to kludge around the problem you could wrap that bit of code in conditional logic. Define and set a variable that determines the desired state of the f-selection frame and use that to control the sensitivity logic:
define variable f-shouldBeVisible as logical no-undo.
if .... then
f-shouldBeVisible = yes.
else
f-shouldBeVisible = no.
...
else
do:
if f-shouldBeVisible then
assign ll-lgst-key1:SENSITIVE in frame f-selection = TRUE
ll-lgst-key2:SENSITIVE in frame f-selection = FALSE
.
end.
Of course that looks kind of silly -- but it is just an example with grossly over-simplified logic.
OTOH if you know enough to set the variable you ought to be able to figure out why the ELSE branch is executing. But maybe it is a useful first step.

How to deselect cells in uitable / how to disable cell selection highlighting?

I created the following uitable:
actually every single row is an indpendent uitable, so the figure shown contains 5 uitables besides the header. Why I'm doing that was the issue of my last question, resulting in the shown table. Fully executable code you can find in the answer here (or a minimal example below). Solutions using a general GUI are also there, but it would blow up the code too much, and actually it just seems to be a kind of bug.
It can be seen that everytime I jump to the next row, therefore to another uitable, the last selection remains highlighted, which looks stupid, though it doesn't matter for the functionality.
There is the 'SelectionHighlight' property for uitables, sounds like a solution, but it is not changing anything. I used it as following:
set(src,'SelectionHighlight','off') %where src is the handle of the current uitable
at various places: at the end of a 'CellSelectionCallback', at the end of a 'CellEditCallback' and as global property. But everytime the last cell remains selected. Actually I don't need selection at all.
How can I disable the whole selection or selection highlighting property for all my uitables?
How do I have to use this property, that it has an effect?
Alternatively: how can I change the "highlighting" color (and therefore text-color) so the highlighting is just not visible anymore?
Apparently this issue appears also in other contexts.
I created a minimum executable example, where one can select a number between 1 and 3 in every row.
function minimalTable
%basic properties
line_height = 21.32;
table_height = 3*line_height;
lh = line_height/table_height;
h = figure('Position',[200 100 202 table_height],'numbertitle','off','MenuBar','none');
% addrow(figurehandle,number of row, percentage lineheight)
% every function call creates a new row, later dynamically
addRow(h,1,lh);
addRow(h,2,lh);
addRow(h,3,lh);
end
function modifySelection(src,~)
set(src,'SelectionHighlight','off')
waitfor(src)
end
function [th] = addRow(fh,k,lhp)
selector = { '1'; '2' ; '3' };
defaultData = {'select number...'};
columnformat = { {selector{:}} };
columneditable = true;
th = uitable(fh,'Units','normalized','Position',[0 1-k*lhp 1 lhp],...
'Data', defaultData,...
'ColumnName', [],...
'ColumnWidth', {200},...
'ColumnEditable', columneditable,...
'ColumnFormat', columnformat,...
'RowName',[],...
'SelectionHighlight','off',...
'CellEditCallback',#modifySelection);
end
results in:
After some deeper research I found out, that the Matlab Support comes out with the following solution:
%overwrite data with a dummy and restore the old data afterwards, to force deselection
function modifySelection(src,~)
...
temp = get(src,'Data')
set(src,'Data',{ 'dummy' });
set(src,'Data', temp );
end
Doing this the blue highlighting is gone, BUT the dotted line around the last selected cell remains!
But I found a solution resolving this, which also makes the first part dispensable.
function modifySelection(src,evt)
...
fh = get(src,'parent'); % get parent figure handle
copyobj(src,fh); % copy uitable to parent figure
delete(src); % delete current uitable
end
Which results in the desired behaviour:
Drawback of the second solution: it lags a little (probably just on slow machines), because of the creation of a new object.
Allright, I found a solution for deselecting cells:
First of all, this requires some Java. But dont worry, it will still look like Matlab :)
1. You will need the script findjobj by Yair Altman: TMW File-Exchange: findjobj
2. You need the handle of your table, lets call it mtable. Then you need the underlying Java-table and do some stuff to get the right objects and set some properties. You can do this by:
jscroll=findjobj(mtable);
h=jscroll.getComponents;
viewport=h(1);
a=viewport.getComponents;
jtable=a(1); %com.mathworks.hg.peer.ui.UITablePeer
jtable.setRowSelectionAllowed(0);
jtable.setColumnSelectionAllowed(0);
3. Now the more tricky part (at least it was for me): If you have some Callback for CellSelectionChanged, but you dont want to excecute this now, you have to turn it off temporary:
set(mtable, 'CellSelectionCallback', []);
Now you can change the selection by:
jtable.changeSelection(row-1,col-1, false, false);
%Java-> zero ^= one <-Matlab
And now, I was expecting, when setting the CellSelectionCallback back to its original function, everything would be fine. Nope, it was excecuting the Callback. I still dont know the exact reason, but it seems to me, that calling jtable.changeSelection() the selection changes and then is calling the specified Callback, but the caller function is not waiting while this process is running. So what I tried (and I dont know if this is the best way to do it, but it is working very well) is to just pause for a second and then set the Callabck back:
pause(1)
set(mtable, 'CellSelectionCallback', #myOriginalFunction);
4. Now just one more thing: My purpose was just to change the selection to some other cell. Yours is to deselect. I dont know anything about the Java components, but I succeeded by just setting the row/column parameter to -1:
jtable.changeSelection(-1,-1, false, false);
Finally I managed to solve this problem by using many things explained on undocumentedmatlab.com and other posts. I am not sure if all the lines are necessary to call. Note, that this will only be available for the documented Matlab-uitable which appears first in Version 2008 (a or b, I'm not sure about that).
EDIT there are a lot of other functions/parameters etc. you can use, that are undocumented. Just to see what is possible, you can take a look with the autocomplete. Just use it on the jtable. and Tab will display them. For a documentation on those elements you should probably search for a Java-doc.
Just a small "dynamic" minimal example (wait 3 seconds to see a change ;-) ):
function startUitable()
xDat=ones(5,3);
h=figure('Tag','TestFigure');
mtable=uitable('Tag','TestUITABLE');
rowField=uicontrol('units','normalized','Style','edit','Position',[0.4 0.9 0.1 0.1],'parent',h,'Tag','rowField');
colField=uicontrol('units','normalized','Style','edit','Position',[0.6 0.9 0.1 0.1],'parent',h,'Tag','colField');
set(mtable, 'Units','normalized','Position',...
[0.01 0.01 0.8 0.8], 'Data', xDat,...
'ColumnEditable', [false, false,false],...
'ColumnWidth', 'auto')
myButton=uicontrol('units','normalized','Style','pushbutton','parent',h,'Position',[0.04 0.9 0.3 0.1],'String','change Selection')
set(myButton,'Callback',#changeSelection)
end
function changeSelection(~,~,~)
mtable=findobj('Tag','TestUITABLE');
jscroll=findjobj(mtable);
h=jscroll.getComponents;
viewport=h(1);
a=viewport.getComponents;
jtable=a(1); %com.mathworks.hg.peer.ui.UITablePeer
% jtable.setRowSelectionAllowed(0);
% jtable.setColumnSelectionAllowed(0);
row=str2num(get(findobj('Tag','rowField'),'String'));
col=str2num(get(findobj('Tag','colField'),'String'));
jtable.changeSelection(row-1,col-1, false, false);
end

Fixed blocks in simulink diagram

Is there any solution for fixing a block in simulink diagram, to disable moving/resizing for the block ?
Is there any solution to draw kind of a shape in simulink (empty rectangles) ?
my aim is to fix an area in the model, so that the user is not allowed to design the model outside this area.
I tried using the callback functions with no success.
Thanks for any help.
As far as I know there is just a compromise.
As mentioned in the other answer you need to create a subsystem. In the block parameters you can set ReadOnly, so everything is fixed and greyed out, as you desired, or NoReadOrWrite access, so it is completely blocked. This solution works just for "naive" users as they can still change the properties to get access again. Maybe you find a way to prevent the user from entering the properties menu.
The secure way is much more complicated: protected Models
Regarding your question about the rectangular shape: I tried to find a solution for a long time and I'd say there is no way to "draw" something, though the backround is actually called "canvas" ;)
To your other comment: what is wrong about a subsystem? You can just block everything except the block you want the user to play around with. It opens in a new tab/window and it doesn't matter how big is everything. What you want is probably not possible in that manner.
You can achieve that to some extent using callback functions. For example let's have LoadFcn as:
A=get_param(gcb, 'Position');
and MoveFcn as
try
set_param(gcb, 'Position', A);
catch
end
This will prohibit moving and resizing, but not cut or delete. Obviously, this will pollute the workspace so you need to think of a way to manage that. If you want this for many blocks you can add the position to the userData property of block currBlock by
set_param(currBlock, 'UserData', get_param(currBlock, 'Position'));
and then just add this to the block's MoveFcn callback
try
set_param(gcb, 'Position', get_param(gcb, 'UserData'));
catch
end
You can even do this programmatically
moveFcn = sprintf([...
'try\n' ...
' set_param(gcb, ''Position'', get_param(gcb, ''UserData''));\n' ...
'catch\n' ...
'end\n']);
set_param(currBlock, ...
'UserData', get_param(currBlock, 'Position'), ...
'MoveFcn', moveFcn);
Did you tried using blocks? See this example: http://blogs.mathworks.com/seth/2008/07/27/how-to-make-your-own-simulink-block/

Uitable, cellSelectionCallback and modifying dataset

My code is really too long to be posted here, even by little portions. So I will just ask for one or two things :
It appears to me that when modifying the 'Data' property of an uitable 'ht' :
set(ht, 'Data', something);
that the "cellSelectionCallback" routine is triggered (as the selection is very likely to have changed, indeed), but not immediatly after the dataset is modified.
Is this true ?
Is there any way to prevent such a behavoir ?
Thanks !
I have code using a uitable, e.g:
tbl = uitable('Parent', fh, 'CellSelectionCallback',{#cell_select_callback fh});
I did a quick experiment and when using set(tbl,'Data',my_data) the callback is triggered only if the set causes the selected cell(s) to change, and this happens immediately (as far as I can tell - I saw no appreciable delay).
To stop that happening you could just unset the CellSelectionCallback property, change the data, and then reset CellSelectionCallback.
I had the same issue. Was getting index out of bounds warnings. To get rid of those I used this in my CallSelectionCallback:
if ~isempty(eventdata.Indices)
// all the code
end
When the set command triggers the CallSelectionCallback the eventdata.Indices is empty.
A similar possibility to Sebastien's answer is to put this in your cellselectioncallback function:
function output = mycellselection(source,event)
if isempty(event.Indixes)
output = [];
return
end
% rest of your code for cell selection
end
If you don't have any output needed, you can just remove it. I just put it in there to remind you that you have to assign a value to any outputs.

Why Seting the SetMode to orbit disables custom KeyPressFcn event handlers, the callback

1-The code below displays the properties of the pressed key.Try it by pressing a key and observe the results.
figure('Name','Press keys to put event data in Command Window',...
'KeyPressFcn',#(obj,evt)disp(evt));
you will see outputs like this( e.g upon pressing space bar)
Character: ' '
Modifier: {1x0 cell}
Key: 'space'
2-Now simply add the following line of code to above ( or simply execute it before clearing the workspace)
cameratoolbar('SetMode','orbit');
Now press any key and nothing happens! the control will no longer be transferred to your costume call back function! ( here:#(obj,evt)disp(evt)).
same thing happens for WindowButtonDownFcn, WindowButtonUpFcn too.
How can I get around this? I wanna be able to handle KeyPressFcn or WindowButtonDownFcn after executing cameratoolbar('SetMode','orbit').
I found the answer: Once the cameratoolbar('SetMode','orbit') is called one of these two happens:the handle to the figure is lost or the event handler gets its default value. I am not sure which one though. Therefore we can add the following code to re-assign the lost handler back to our own call back function:
set(gcf,'KeyPressFcn',#(obj,evt)disp(evt))