Matlab 是否有可能防止弹出一个可用的弹出菜单?或者:如何通过单击单元格,返回行&;列索引?
对于用户界面,我正在编写一个Matlab 是否有可能防止弹出一个可用的弹出菜单?或者:如何通过单击单元格,返回行&;列索引?,matlab,user-interface,user-controls,callback,matlab-uitable,Matlab,User Interface,User Controls,Callback,Matlab Uitable,对于用户界面,我正在编写一个uitable。用户在第一列中选择一个选项A、B或C,第二列中的子选项取决于在第一列中选择的选项A.1、A.2或A.3或B.1、B.2或B.3或C的相同选项 该表的代码可在附录A中找到 当用户首次定义主选项时,子选项将自动相应地减少为仅有效选项。这是通过为第1列评估CellEditCallback并为第2列重置ColumnFormat实现的。(附录B中的功能modifySelection) 如果用户现在意识到自己犯了错误,需要再次编辑子选项,则ColumnForma
uitable
。用户在第一列中选择一个选项A、B或C,第二列中的子选项取决于在第一列中选择的选项A.1、A.2或A.3或B.1、B.2或B.3或C的相同选项
该表的代码可在附录A中找到
当用户首次定义主选项时,子选项将自动相应地减少为仅有效选项。这是通过为第1列评估CellEditCallback
并为第2列重置ColumnFormat
实现的。(附录B中的功能modifySelection
)
如果用户现在意识到自己犯了错误,需要再次编辑子选项,则ColumnFormat
仍将根据先前编辑的主选项进行设置,并且有效选项不可用,除非他再次重新选择主选项。(参见图中的蓝色突出显示)
为了解决这个问题,我还实现了CellSelectionCallback
调用函数justifySelection
(在附录B中),该函数通过选择进行检查,在第1列中选择了哪个选项,以再次为第2列提供正确的子选项。但是,由于此回调对选择有反应,我需要选择两次,一次触发CellSelectionCallback
,另一次实际获取我的选择。对于大桌子,这可能是非常烦人的
所以我的问题是:
是否有办法防止第2列中的弹出菜单弹出,直到它找到第1列的内容,从而立即提供有效的选项?
或:
如何检测鼠标单击单元格并获取行和列索引?但不调用以下选择和弹出操作?
我已经把所有的东西都翻了一遍,但没有找到任何有用的东西。
也许可以使用按钮DOWNFCN
做些什么,但是如何获取单元格索引呢?那么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
,它重写了列格式
:
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对象属性等的复杂解决方案。提前谢谢
我将评论中的讨论包括在这里,以保持概述: 如果您想尝试,可以复制代码并按照以下步骤重现不希望出现的行为:
ColumnFormat
然后最后让单元格弹出。唯一
到目前为止,我看到的可能性是CellSelectionCallback
,但事实并非如此
在单元格已弹出无效选项后执行。
我需要一种点击回调
,就像按钮
或者确保选择主选项仅设置该行的子选项
这是不可能的,您不能为某一行设置子选项,因为您需要修改
ColumnFormat
,这会影响整个表,而不仅仅是一行。解决方案是在GUI中使用带有两个UITables的单元格选择回调。使第一个表保存{'a'、'b'、'c'}的数据,然后在单元格选择回调中,使第二个UITable可见,并根据第一个UITable的单元格选择属性设置其数据。如果你往下看“一个不需要findjobj的小黑客”一行,这个链接应该有你所需要的一切
虽然我高度赞赏Rody Oldenhuis的努力和解决方案,他绝对值得获奖,但他的解决方案需要对我的代码进行大量修改,因此我一直在尝试寻找更简单的解决方案。在这里,它终于99%的错误免费 (函数脚本中的所有代码部分)
显示:
我不会使用
uitable
;它不适合做这种事情
我会这样做:
function GUIdemo
%%// Construct GUI
%// Main figure
mainFig = figure;
set(mainFig, 'Color', get(0, 'DefaultUicontrolBackgroundColor'));
%// Create as many blocks as needed. The only thing you have to do is
%// figure out the "right" positions for each block
popupHandles = create_ui_blocks([
0.00 0.50 1.00 0.35
0.00 0.15 1.00 0.35]);
%// This OK button gathers all selected options, and just prints them.
uicontrol(...
'style' , 'pushbutton',...
'units' , 'normalized',...
'parent' , mainFig,...
'position', [0.4 0.01 0.2 0.1],...
'callback', @(~,~)getData(popupHandles),...
'string' , 'OK'...
);
%%// Helper functions
%// Create control blocks. Each block is composed of:
%// - a uipanel as container
%// - three radio buttons for the main selection
%// - a corresponding popup or the secondary selection
function popupHandles = create_ui_blocks(positions)
%// initialize
numBlocks = size(positions,1);
panels = zeros(numBlocks,1);
groups = zeros(numBlocks,1);
radios = zeros(numBlocks,3);
popups = zeros(numBlocks,1);
%// Build each block
for ii = 1:numBlocks
%// The container
panels(ii) = uipanel(...
'parent' , mainFig,...
'position', positions(ii,:)...
);
%// The radio buttons
groups(ii) = uibuttongroup(...
'parent' , panels(ii),...
'position', [0.05 0.05 0.45 0.9]...
);
radios(ii,1) = uicontrol(...
'style' , 'radio',...
'units' , 'normalized',...
'string' , 'A',...
'parent' , groups(ii),...
'position', [0.05 0.66 0.9 0.25]...
);
radios(ii,2) = uicontrol(...
'style' , 'radio',...
'units' , 'normalized',...
'string' , 'B',...
'parent' , groups(ii),...
'position', [0.05 0.33 0.9 0.25]...
);
radios(ii,3) = uicontrol(...
'style' , 'radio',...
'units' , 'normalized',...
'string' , 'C',...
'parent' , groups(ii),...
'position', [0.05 0.0 0.9 0.25]...
);
%// Initially, nothing's selected
set(groups(ii), 'SelectedObject',[]);
%// The popups
popups(ii) = uicontrol(...
'style' , 'popup',...
'units' , 'normalized',...
'parent' , panels(ii),...
'position', [0.55 0.4 0.4 0.2],...
'string' , 'Select main option',...
'enable' , 'off'...
);
%// On changing radiobutton, correct the string list of the popups
set(groups(ii),'SelectionChangeFcn', @(~,~)selectionChangeCallback(ii));
%// This is needed by the OK button callback
popupHandles = popups;
end
%// What happens when clicking a radio button?
%// NOTE: this is a doubly-nested function
function selectionChangeCallback(num)
switch get(groups(num), 'SelectedObject')
case radios(num,1)
set(popups(num), 'string', {'A.1', 'A.2', 'A.3'}, 'enable', 'on');
case radios(num,2)
set(popups(num), 'string', {'B.1', 'B.2', 'B.3'}, 'enable', 'on');
case radios(num,3)
set(popups(num), 'string', {'C.1', 'C.2', 'C.3'}, 'enable', 'on');
otherwise
%// ...
end
end
end
%// What happens when pressing the OK button?
function data = getData(popupHandles)
data = char(cellfun(@(x,y)x{y}, ...
get(popupHandles, 'String'),...
get(popupHandles, 'Value'),...
'UniformOutput', false)) %#ok<NOPRT> //
end
end
布局当然仍然粗糙,但你明白了。当然,单选按钮也可以替换为一个弹出窗口(更紧凑)、三个按钮或任何您喜欢的按钮
弹出窗口的内容彼此不相关,这正是uitable
方法的问题所在。在这个GUI中,更改单选按钮时,弹出窗口内容的更改可以是即时的,因为您可以更好地控制如何处理更改
function edit(src,evt)
if evt.Indices(2) == 1
modifyPopup( src,evt.Indices(1) );
end
% disables cell selection highlighting, when one jumps to next table,
% a bit laggy though
fh = get(src,'parent');
copyobj(src,fh);
delete(src);
end
function modifyPopup( src,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 output file first'};
config_data = get(src,'Data');
selector = config_data(row,1);
selector = selector{1};
config_format = get(src,'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
config_data = { selector , 'select suboption...' }; %reset column 2
set(src,'Data',config_data);
set(src,'ColumnFormat',config_format);
end
function addRow(fh,k,lhp)
selector_1 = { 'A'; 'B' ; 'C' };
selector_2 = { 'first select first row!' };
defaultData = {'select main option...', 'select suboption...'};
columnformat = { {selector_1{:}}, selector_2};
columneditable = [true true];
th = uitable(fh,'Units','normalized','Position',[0 1-(k+1)*lhp 1 lhp],...
'Data', defaultData,...
'ColumnName', [],...
'ColumnWidth', {200 200},...
'ColumnEditable', columneditable,...
'ColumnFormat', columnformat,...
'RowName',[],...
'Tag','value',...
'UserData',k,...
'SelectionHighlight','off',...
'CellEditCallback',@edit);
end
function store(~,~)
ui = findobj(0,'Type','uitable','Tag','value');
L = numel(ui);
output = cell(L,2);
order = zeros(L,1);
for ii=1:L;
output(ii,:) = get(ui(ii),'Data');
order(ii) = get(ui(ii),'UserData');
end
[~,idx] = sort(order); %as order of handles unequals displayed order
assignin('base','output',output(idx,:));
end
function GUIdemo
%%// Construct GUI
%// Main figure
mainFig = figure;
set(mainFig, 'Color', get(0, 'DefaultUicontrolBackgroundColor'));
%// Create as many blocks as needed. The only thing you have to do is
%// figure out the "right" positions for each block
popupHandles = create_ui_blocks([
0.00 0.50 1.00 0.35
0.00 0.15 1.00 0.35]);
%// This OK button gathers all selected options, and just prints them.
uicontrol(...
'style' , 'pushbutton',...
'units' , 'normalized',...
'parent' , mainFig,...
'position', [0.4 0.01 0.2 0.1],...
'callback', @(~,~)getData(popupHandles),...
'string' , 'OK'...
);
%%// Helper functions
%// Create control blocks. Each block is composed of:
%// - a uipanel as container
%// - three radio buttons for the main selection
%// - a corresponding popup or the secondary selection
function popupHandles = create_ui_blocks(positions)
%// initialize
numBlocks = size(positions,1);
panels = zeros(numBlocks,1);
groups = zeros(numBlocks,1);
radios = zeros(numBlocks,3);
popups = zeros(numBlocks,1);
%// Build each block
for ii = 1:numBlocks
%// The container
panels(ii) = uipanel(...
'parent' , mainFig,...
'position', positions(ii,:)...
);
%// The radio buttons
groups(ii) = uibuttongroup(...
'parent' , panels(ii),...
'position', [0.05 0.05 0.45 0.9]...
);
radios(ii,1) = uicontrol(...
'style' , 'radio',...
'units' , 'normalized',...
'string' , 'A',...
'parent' , groups(ii),...
'position', [0.05 0.66 0.9 0.25]...
);
radios(ii,2) = uicontrol(...
'style' , 'radio',...
'units' , 'normalized',...
'string' , 'B',...
'parent' , groups(ii),...
'position', [0.05 0.33 0.9 0.25]...
);
radios(ii,3) = uicontrol(...
'style' , 'radio',...
'units' , 'normalized',...
'string' , 'C',...
'parent' , groups(ii),...
'position', [0.05 0.0 0.9 0.25]...
);
%// Initially, nothing's selected
set(groups(ii), 'SelectedObject',[]);
%// The popups
popups(ii) = uicontrol(...
'style' , 'popup',...
'units' , 'normalized',...
'parent' , panels(ii),...
'position', [0.55 0.4 0.4 0.2],...
'string' , 'Select main option',...
'enable' , 'off'...
);
%// On changing radiobutton, correct the string list of the popups
set(groups(ii),'SelectionChangeFcn', @(~,~)selectionChangeCallback(ii));
%// This is needed by the OK button callback
popupHandles = popups;
end
%// What happens when clicking a radio button?
%// NOTE: this is a doubly-nested function
function selectionChangeCallback(num)
switch get(groups(num), 'SelectedObject')
case radios(num,1)
set(popups(num), 'string', {'A.1', 'A.2', 'A.3'}, 'enable', 'on');
case radios(num,2)
set(popups(num), 'string', {'B.1', 'B.2', 'B.3'}, 'enable', 'on');
case radios(num,3)
set(popups(num), 'string', {'C.1', 'C.2', 'C.3'}, 'enable', 'on');
otherwise
%// ...
end
end
end
%// What happens when pressing the OK button?
function data = getData(popupHandles)
data = char(cellfun(@(x,y)x{y}, ...
get(popupHandles, 'String'),...
get(popupHandles, 'Value'),...
'UniformOutput', false)) %#ok<NOPRT> //
end
end
data =
A.1
B.1