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

2

7

I created the following uitable:

bug

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:

min_example

Caboose answered 28/10, 2013 at 12:0 Comment(2)
All this to fix a relatively small bug that was essentially not really a problem :) Very glad to see you don't give up easily, good on you. You solved it all yourself :)Uvular
never leave your workers bored and unattended ;)Caboose
C
4

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:

enter image description here

Drawback of the second solution: it lags a little (probably just on slow machines), because of the creation of a new object.

Caboose answered 29/10, 2013 at 9:39 Comment(6)
+1 nice to see, that there is some workaround and thanks for posting it! But I guess this could lead to some problems for bigger tables...Affined
problems of which kind? performance? It just affects one table with one row (in this case) - so I'd guess it won't get worse than on my 6 year old machine where it lags maybe some milliseconds. The only thing which could be a little annoying, is that you completely screw up your handle definitions as copy(...) does not allow to give the copy an actual name.Caboose
hmm maybe I got something wrong, but dont you copy the whole uitable for that? and if so, I can imagine, that the performance will get slow, if you have bigger tables. Perhaps setting visibiliy off and on or a "drawnow" could help in such a case. Another solution could be found with using Java: undocumentedmatlab.com/blog/uitable-cell-colors -> using setting set(jtable,'SelectionBackground',someJavaColor) as described in the comments. Perhaps I will find some minutes to try out something...Affined
@LuciusDomitiusAhenobarbus The reason why the issue occurs is that I don't have "one" uitable - I have (for this example) 6 uitables - and after every cell edit, just the particular uitable, which got edited is copied and deleted. So even if you have large tables, they consist of a lot of little tables. Of course one could apply the workaround on big "normal" tables also, but in this case usually the problem wouldn't occur ;) The java solution may be the best. But I never get it work...Caboose
After nearly 4 years the question was asked, is there any easier solution to this annoying behavior?Hydra
@DiaaAbidou I'm not developing GUIs anymore, but since 2013 there were a lot of changes in the graphics engine and you could give it try. Or ask a new question - but put some own effort into it also.Caboose
A
1

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
Affined answered 6/11, 2013 at 8:31 Comment(8)
I wonder, as there is a command like setRowSelectionAllowed - why couldn't I just disable selection completely? It occurs to me, that this property is changed with every callback, right? Have you tried this approach with the minimal example? I actually wasn't able to make anything work the last weeks, involving the findjobj package with R2013a. But I'll try your solution.Caboose
if you set ColumnEditable', [false, false ,false] your whole code starting with "jscroll" doesn't seem to have any effect. (of course I downloaded the findjobj package) The selection behaviour is like before. Also when I implement your code in my own minimal example I get "Attemmpt to reference field of non strcture array" in the line jtable.setRowSelectionAllowed(0).Caboose
well, wait, I maybe have to put it into the callback and not into the main function. ... but then I get the reference error again. So maybe it could work, if one could make run your code inside the CellSelectionCallback.Caboose
the minimal example is just for demonstrating how to deselect. if you have some CellSelectionCallback defined, you have to look at #3 !! it is important to temporary deselect a CellSelectionCallback and to wait for the changeSelection-functionAffined
Yes I got that, it still has the reference error. And also your example without a CellSelectionCallback just works once for the first selected cell, and never again.Caboose
well, just leave out the setRowSelectionAllowed and same for Column. This was from an example, where someone wanted to select more then just one cell. what exactly doesnt work? I try to make another example to test it...Affined
your example with 'ColumnEditable', [false, false ,false] deselects the initial selected cell after 3sec. If you select other cells afterwards there is no effect anymore. Now I considered all your points and wrote the code into the CellSelectionCallback. Instead of row=2;col=2; I use the indices I get from the eventdata. But everytime I want to access somehting with jtable. ... I get the already mentioned "Attemmpt to reference field of non strcture array" error. Mabye it has to do with the new version of matlab, I could imagine that. `Caboose
let us continue this discussion in chatAffined

© 2022 - 2024 — McMap. All rights reserved.