matlab - 是否可以防止弹出合适的弹出菜单?或者 : How to get a callback by clicking a cell, 返回行和列索引?

标签 matlab user-interface user-controls callback matlab-uitable

对于用户界面,我正在编写 uitable .用户在第一列中选​​择一个选项 A、B 或 C,第二列中的子选项取决于第一列中的选择,A.1、A.2 或 A .3B.1、B.2 或 B.3C

enter image description here

表格的代码可以在附录A中找到。

当用户首先定义主要选项时,子选项会自动相应地减少为只有有效的选择。这是通过评估 CellEditCallback 来实现的对于第 1 列并重置 ColumnFormat对于第 2 列。(附录 B 中的函数 modifySelection) 如果用户现在意识到他犯了错误并需要再次编辑子选项,那么 ColumnFormat仍然根据先前编辑的主要选项设置并且有效选择不可用,除非他再次重新选择主要选项。 (请参阅图片中的蓝色突出显示部分)。

为了解决这个问题,我还实现了 CellSelectionCallback调用函数 justifySelection (在 附录 B 中),它通过选择检查,在第 1 列中选择了哪个选项以再次为第 2 列提供正确的子选项。但是由于此回调对选择使用react,我需要选择 两次,一次触发CellSelectionCallback另一个真正让我做出选择。对于大表,这可能非常烦人!

所以我的问题是:

有没有办法阻止第2列的弹出菜单弹出,直到它找到相应的第1列的内容,然后立即提供有效的选择?

或者:

我如何检测鼠标点击单元格并获取行和列索引?但是没有调用下面的选择和弹出 Action ?

我已经在收集所有 available properties但没有发现任何有用的东西。 也许可以使用 ButtonDownFcn 做点什么,但如何获得单元格索引?那BusyAction呢?属性(property),它怎么能用于我的目的?

有什么想法吗?

很抱歉提前用这么多代码轰炸你,它已经是最小的例子,但是完全可执行,所以你可以试试看。


附录 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(尽管在不同的行中)。

It seems that instead of looking for the last option, you should look at the relevant option. So either make sure that clicking on a suboption does a 'lookup' to see which main option there is,

Thats exactly what I'm looking for! But how could I do that? How to detect the click, get the column&row indices, set the right ColumnFormat and then finally let the cell pop up. The only possibility I see until now is the CellSelectionCallback, but it is executed after the cell already popped up with the invalid choices. I'd need a kind of ClickedCallback, like there is for pushbuttons

或者确保选择主选项只会设置该行的子选项。

那是不可能的,你不能为某一行设置子选项,因为你需要修改ColumnFormat ,这会影响整个表格,而不仅仅是一行。

最佳答案

我不会使用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

enter image description here enter image description here

按下“确定”键时 MATLAB 命令窗口中的输出:

data =
    A.1
    B.1

布局当然还很粗糙,但你明白了。当然,单选按钮也可以替换为弹出窗口(更紧凑)、三个按钮或您喜欢的任何其他内容。

弹出窗口的内容彼此不相关,这正是 uitable 方法的问题。在此 GUI 中,当更改单选按钮时,弹出内容的更改可能是即时的,这仅仅是因为您可以更好地控制如何处理更改。

编程注意事项:我个人不喜欢我视为“ block ”的各个组件的句柄在顶层函数中 float ,这就是我使用双重嵌套函数的原因——它是有点像封装。现在,在课外使用时,这不是每个人都喜欢的,所以您可能想要转换它们。当然,所有嵌套函数都被简单地转换为子函数;您只需要手动传递更多信息。

使用这种方法,您将失去一些功能(调整 UI 元素大小的能力),但您获得 GUI 控件的直观行为。当这些是选择时,我已经接受过向后一种选择发展的训练。漂亮的花里胡哨只会在前几次给最终用户留下深刻印象,但随着使用量的增加,该程序的基本功能将变得越来越重要。正如您自己指出的那样,当您不得不经常使用该工具时,这种错误行为会变得烦人;我会说,放弃可调整大小以支持改进的控制行为。

关于matlab - 是否可以防止弹出合适的弹出菜单?或者 : How to get a callback by clicking a cell, 返回行和列索引?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19406767/

相关文章:

matlab - 如何计算系列的总和,直到总和在 Matlab 中停止变化

matlab - fvtool生成的数字亲子关系破裂?

matlab - 如何以编程方式调用 MatLab 中的缩放事件?

JavaFx 不需要的白色角 - TextArea

matlab - 如何在 GUI 运行时拦截 Matlab 中的击键

java - setHorizo​​ntalAlignment(CENTER) - CENTER 无法解析为变量

c# - 绑定(bind)未按预期更新

.net - 在.net中查找控件

matlab - 递归添加函数句柄并在打印后查看正确输出的正确方法是什么?

xaml - WP7 - 在类型 'Resources' 中找不到可附加属性 'PhoneApplicationPage'