我正在编写一个用户界面,其中包括一个 uitable
。用户在第一列中选择选项 A、B 或 C,第二列的子选项取决于第一列选择了什么,可以是 A.1、A.2 或 A.3,也可以是 B.1、B.2 或 B.3,或者与 C 相同。
表格的代码可以在附录A中找到。
当用户首先定义主选项时,自动减少子选项以仅显示有效选择。这是通过评估第1列的CellEditCallback
并重置第2列的ColumnFormat
来实现的。(函数modifySelection
在附录B中)
如果用户现在意识到他犯了一个错误并需要再次编辑子选项,则ColumnFormat
仍根据先前编辑的主选项设置,除非他再次选择主选项,否则有效选择不可用(请参见图片中的蓝色突出显示)。
为解决此问题,我还实现了CellSelectionCallback
调用函数justifySelection
(在附录B中),它通过选择检查选择了哪个选项来提供正确的第2列子选项。但由于此回调对选择做出反应,因此我需要选择两次,一次触发CellSelectionCallback
,另一次实际获取我的选择。对于大型表格,这可能非常麻烦!
所以我的问题是:
有没有办法防止第2列中的弹出菜单在找到相应的第1列内容之前弹出,以便它立即提供有效的选择?
或:
如何检测单元格上的鼠标单击并获取行和列索引?但不触发以下选择和弹出操作?
我已经遍历了所有可用属性,但没有找到任何有用的东西。也许可以使用ButtonDownFcn
做些什么,但如何获取单元格索引?BusyAction
属性怎么样,如何用于我的目的?
有什么想法吗?
事先很抱歉给你带来这么多代码,这已经是最简化的例子,但是完全可执行,所以您可以尝试一下。
附录 A/B
function fancyUitable
selector_1 = { 'A'; 'B' ; 'C' };
selector_2 = { 'first select first row!' };
h = figure('Position',[200 100 268 120],'numbertitle','off','MenuBar','none');
defaultData = repmat( {'select main option...', 'select suboption...'} ,5,1);
columnname = {'Option ',...
'Suboption '};
columnformat = { {selector_1{:}}, selector_2 };
columneditable = [true true];
t = uitable(h,'Units','normalized','Position',[0 0 1 1],...
'Data', defaultData,...
'ColumnName', columnname,...
'ColumnEditable', columneditable,...
'ColumnFormat', columnformat,...
'RowName',[],...
'CellEditCallback',@modifySelection,...
'CellSelectionCallback',@justifySelection);
set(h,'Tag','Config_figure')
set(t,'Tag','Config_table')
end
% **Appendix B**
% (part of the same function file)
function modifySelection(~,evt_edit)
if evt_edit.Indices(2) == 1
modifyPopup( evt_edit.Indices(1) );
end
end
function justifySelection(~,evt_select)
try %to surpress an unimportant error
if evt_select.Indices(2) == 2
modifyPopup( evt_select.Indices(1) );
end
end
end
最后是单一函数modifyPopup
,它重写了Columnformat
:
function modifyPopup( row )
id_group_1 = {'A.1';'A.2';'A.3'};
id_group_2 = {'B.1';'B.2';'B.3'};
id_group_3 = {'C.1';'C.2';'C.3'};
id_default = {'select main option first'};
myfigure = findobj('Tag','Config_figure');
config_data = get(findobj(myfigure,'Tag','Config_table'),'Data');
selector = config_data(row,1);
selector = selector{1};
config_format = get(findobj(myfigure,'Tag','Config_table'),'ColumnFormat');
switch selector
case 'A'
config_format{2} = id_group_1';
case 'B'
config_format{2} = id_group_2';
case 'C'
config_format{2} = id_group_3';
otherwise
config_format{2} = id_default;
end
set(findobj(myfigure,'Tag','Config_table'),'ColumnFormat',config_format)
end
赏金:为什么只有50加分?-我猜要么不可能,要么答案很简单,一旦有了正确的初始想法。我不想使用Java对象属性等复杂的解决方法。提前谢谢!
我在这里包含评论中的讨论以保持概述:
如果您想尝试它,请复制代码并按照以下步骤重现不希望发生的行为:
1. 在第一行中选择主选项A。 2. 然后,第一行的子选项包含选择A.1、A.2和A.3。 3. 选择第二行中的主选项B,因此第二行的子选项选择是B.1、B.2和B.3。 4. 但现在您想直接更改第一行中的子选项;您期望获得A.1、A.2和A.3的选择;但您没有。您得到了提供的B.1、B.2和B.3;-因为您上次选择的最后一个主选项是B(尽管在不同的行中)。
似乎不是寻找最后一个选项,而是寻找相关选项。因此,请确保单击子选项会进行“查找”,以查看哪个主选项存在。 这正是我在寻找的!但我该如何做到呢?如何检测点击、获取列和行索引、设置正确的“ColumnFormat”,然后最终让单元格弹出。到目前为止,我唯一看到的可能性是“CellSelectionCallback”,但它是在单元格已经弹出并显示无效选择之后执行的。我需要一种类似于“pushbuttons”中的“ClickedCallback”的方法。
或者确保只选择一个主选项即可设置该行的子选项。这是不可能的,您无法为特定行设置子选项,因为您需要修改“ColumnFormat”,这会影响整个表格,而不仅仅是一行。
ColumnFormat
属性实现的,而这必须是一个行向量。 - Robert Seifert