如何在UITable中取消选择单元格/如何禁用单元格选择高亮显示?

7
我创建了以下uitablebug 实际上,每一行都是一个独立的uitable,所以展示的表格除了表头外包含5个uitable。我这样做的原因是我的上一个问题,导致显示的表格。你可以在这里找到完整可执行代码(或下方提供的最小化示例)。使用通用GUI的解决方法也在那里,但这会使代码过于复杂,实际上它似乎只是一种错误。
可以看到,每当我跳转到下一行,也就是另一个uitable时,上一次的选择仍然保持高亮状态,看起来很愚蠢,尽管这对功能不重要。 'SelectionHighlight'属性适用于uitable,听起来像是解决办法,但是它并没有改变任何东西。我如下使用它:
set(src,'SelectionHighlight','off')  %where src is the handle of the current uitable

在多个地方使用:在 'CellSelectionCallback' 的末尾,在 'CellEditCallback' 的末尾以及作为全局属性。 但是每次最后一个单元格都保持选定状态。 实际上,我根本不需要选择。

如何禁用所有uitables的整个选择或选择突出显示属性?

我应该如何使用此属性才能产生效果?

或者:如何更改“突出显示”的颜色(因此文本颜色)使突出显示不再可见?

显然,这个问题也出现在其他情况中。


我创建了一个最小可执行示例,在其中可以在每行中选择1到3个数字。

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

导致结果:

min_example


所有这些都是为了修复一个相对较小的 bug,实际上并不是真正的问题 :) 很高兴看到你不轻易放弃,做得好。你自己解决了所有问题 :) - Rody Oldenhuis
永远不要让你的工作人员感到无聊和被忽视 ;) - Robert Seifert
2个回答

4

经过深入研究,我发现Matlab支持以下解决方案:

%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

这样做后,蓝色高亮消失了,但最后选择的单元格周围仍然保留了虚线框! 但我发现了一个解决方案,也使第一部分变得可有可无。

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

这将导致所需的行为:

在此输入图片描述

第二个解决方案的缺点是它会有点滞后(可能只是在慢速机器上),因为需要创建一个新对象。


+1 很高兴看到有一些解决方法,谢谢你的发帖!但我猜这可能会给更大的表格带来一些问题... - Lucius II.
这是哪种问题?性能问题吗?它只影响一个表格,只有一行数据(在这种情况下) - 所以我猜想它不会比我的六年前的机器更糟糕,那里可能会有几毫秒的滞后。唯一可能有点烦人的事情是,由于 copy(...) 不允许为复制品指定实际名称,因此您可能会完全搞乱您的句柄定义。 - Robert Seifert
嗯,也许我理解错了,但是你难道不是要复制整个uitable吗?如果是这样的话,当你有更大的表格时,性能可能会变慢。也许在这种情况下,关闭和打开可见性或使用“drawnow”可以帮助解决问题。另一种解决方案可以在使用Java时找到:http://undocumentedmatlab.com/blog/uitable-cell-colors/ -> 如评论中所述,使用set(jtable,'SelectionBackground',someJavaColor)进行设置。也许我会找到一些时间来尝试一些东西... - Lucius II.
@LuciusDomitiusAhenobarbus 发生问题的原因是我没有“一个”uitable - 我有(对于这个例子)6个uitable - 并且在每次单元格编辑之后,只会复制和删除被编辑的特定uitable。因此,即使您有大型表格,它们也由许多小表格组成。当然,人们也可以在大型“正常”表格上应用解决方法,但在这种情况下,通常不会出现问题;) Java解决方案可能是最好的。但我从来没有让它起作用... - Robert Seifert
1
经过将近4年的时间,有没有更简单的解决方案来解决这个令人烦恼的行为? - Diaa
@DiaaAbidou 我不再开发GUI了,但自2013年以来,图形引擎发生了很多变化,你可以尝试一下。或者提出一个新的问题 - 但也要付出一些自己的努力。 - Robert Seifert

1

好的,我找到了取消选择单元格的解决方案:

首先,这需要一些Java。但不用担心,它仍然看起来像Matlab :)

1. 您需要使用Yair Altman的脚本findjobjTMW File-Exchange: findjobj

2. 您需要表的句柄,让我们称其为mtable。然后,您需要获取底层Java表并执行一些操作以获取正确的对象并设置一些属性。您可以通过以下方式完成此操作:

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. 现在是比较棘手的部分(至少对我来说是这样):如果你有一些关于单元格选择更改的回调函数,但是你现在不想执行它,你需要暂时将其关闭:

set(mtable, 'CellSelectionCallback', []);

现在你可以通过以下方式更改选择:

jtable.changeSelection(row-1,col-1, false, false);
%Java-> zero ^= one <-Matlab

现在,我本以为将CellSelectionCallback设置回其原始函数后,一切都会正常。但是不,它仍然执行回调函数。我仍然不知道确切的原因,但在我的看来,调用jtable.changeSelection()会更改选择,然后调用指定的回调函数,但调用者函数在此过程运行时并未等待。因此,我尝试了以下方法(我不知道这是否是最好的方法,但它非常有效),只需暂停一秒钟,然后再设置回调函数:

pause(1)
set(mtable, 'CellSelectionCallback', @myOriginalFunction);

4. 现在只剩下一件事:我的目的只是将选择更改为其他单元格。你的目的是取消选择。我对Java组件一无所知,但我成功了,只需将行/列参数设置为-1

jtable.changeSelection(-1,-1, false, false);

最后,我通过使用undocumentedmatlab.com和其他文章中解释的许多东西,成功解决了这个问题。我不确定是否需要调用所有代码行。请注意,这仅适用于文档化的Matlab可编辑表格,该表格首次出现在2008年版本中(ab,我不确定)。

编辑,还有很多其他未经记录的函数/参数等可供使用。只需使用自动完成功能,在jtable.上使用它,Tab将显示它们。有关这些元素的文档,您可能需要搜索Java-doc。

这只是一个小的“动态”最小示例(等待3秒钟以查看更改;-)):

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

如果您设置ColumnEditable',[false, false ,false],则从“jscroll”开始的整个代码似乎没有任何效果。(当然,我已经下载了findjobj包)选择行为与以前相同。此外,当我在自己的最小示例中实现您的代码时,我会在jtable.setRowSelectionAllowed(0)这一行中得到“尝试引用非结构数组字段”的错误提示。 - Robert Seifert
好的,等一下,我可能必须将它放到回调函数中而不是主函数中。......但是然后我又遇到了引用错误。所以也许如果能在“CellSelectionCallback”内运行您的代码,它可能会起作用。 - Robert Seifert
最小示例只是为演示如何取消选择而设置的。如果您有一些CellSelectionCallback定义,请查看#3!临时取消选择CellSelectionCallback并等待changeSelection函数的更改非常重要。 - Lucius II.
是的,我明白了,它仍然存在引用错误。而且你的例子没有 CellSelectionCallback 只能在第一次选择单元格时工作,之后就再也无法工作了。 - Robert Seifert
好的,只需忽略setRowSelectionAllowed,同样适用于列。这是来自一个示例,其中有人想选择不止一个单元格。具体哪里出了问题?我会尝试创建另一个示例来测试它... - Lucius II.
显示剩余3条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接