【问题标题】:Showing NatTable context menu显示 NatTable 上下文菜单
【发布时间】:2016-04-17 07:55:23
【问题描述】:

我使用 NatTable。如何根据单元格的内容在特定条件下显示上下文菜单项?以及如何选择调用上下文菜单的单元格?我用以下代码绑定菜单

uiBindingRegistry.registerMouseDownBinding(
            new MouseEventMatcher(SWT.NONE, null, MouseEventMatcher.RIGHT_BUTTON), new PopupMenuAction(menu));

统一更新: 我创建这样的菜单,但尽管isActive 总是返回false,但“测试”项仍然可见。它有什么问题?

menu = new PopupMenuBuilder(natTable).withMenuItemProvider(ITEM_ID, new IMenuItemProvider() {
        @Override
        public void addMenuItem(final NatTable natTable, final Menu popupMenu) {
            final MenuItem menuItem = new MenuItem(popupMenu, SWT.PUSH);
            menuItem.setText("Test");
            menuItem.setEnabled(true);
            menuItem.addSelectionListener(new SelectionAdapter() {
                @Override
                public void widgetSelected(final SelectionEvent event) {
                    System.out.println("test");
                }
            });
        }
    }).withVisibleState(ITEM_ID, new IMenuItemState() {
        @Override
        public boolean isActive(final NatEventData natEventData) {
            return false;
        }
    }).build();

【问题讨论】:

  • 如果常量 ITEM_ID 不为 null,则该代码没有任何问题。问题是,你在哪里创建菜单?我直接在 AbstractUiBindingConfiguration 中创建它,它按预期工作。
  • @Dirk Fauth 我找到了原因。在CellPopupMenuAction run() 我有menu.setData(event.data) 但应该有menu.setData(MenuItemProviders.NAT_EVENT_DATA_KEY, event.data)。然后一切都按预期工作。
  • 感谢您的提示...我完全忘记了那个细节。我更新了答案中的示例代码以正确反映这一点。
  • 我又找到原因了bugs.eclipse.org/bugs/show_bug.cgi?id=451490你用的是哪个版本的Eclipse/JFace?
  • @Dirk Fauth 4.3.0/3.9.1

标签: java swt nattable


【解决方案1】:

给出的答案是正确的。虽然可以改进。您不需要 SelectionLayer。

class CellPopupMenuAction implements IMouseAction {

    private final Menu menu;

    public CellPopupMenuAction(Menu menu) {
        this.menu = menu;
    }

    @Override
    public void run(NatTable natTable, MouseEvent event) {
        int columnPosition = natTable.getColumnPositionByX(event.x);
        int rowPosition = natTable.getRowPositionByY(event.y);

        ILayerCell cell = natTable.getCellByPosition(columnPosition, rowPosition);

        if (!cell.getDisplayMode().equals(DisplayMode.SELECT)) {
            natTable.doCommand(
                    new SelectCellCommand(
                            natTable,
                            columnPosition,
                            rowPosition,
                            false,
                            false));
        }

        menu.setData(MenuItemProviders.NAT_EVENT_DATA_KEY, event.data);
        menu.setVisible(true);
    }
}

通过这种方式,您完全无需引用 SelectionLayer,甚至可以改进功能,因为如果您右键单击选定的单元格,则不会触发 SelectCellCommand。

【讨论】:

  • 谢谢。以及如何根据条件(单元格内容)在菜单中显示不同的项目?
  • 如果您使用的是 NatTable PopupMenuBuilder,您可以创建并添加一个 IMenuItemState 来指定启用或可见状态的条件。
  • 我使用 MenuManager。在这种情况下有没有办法使用 IMenuItemState ?
  • 事实上你需要MenuManager来创建PopupMenuBuilder来使用IMenuItemState。对于可以访问 NatTable 内容的 NatTable 上下文菜单,这始终是推荐的方式。
  • 你能看看更新的问题吗?尽管我使用 IMenuItemState 始终为 false,但菜单项始终可见
【解决方案2】:

您需要 IMouseAction 来选择单元格。来自here 的示例代码以及在其中添加的一些附加代码以在下面添加选择调用:

nattable.addConfiguration( new AbstractUiBindingConfiguration()

    uiBindingRegistry.registerMouseDownBinding( new MouseEventMatcher( SWT.NONE, GridRegion.BODY,
                            MouseEventMatcher.RIGHT_BUTTON ), new CellPopupMenuAction(menu, selectionLayer) );


});

class CellPopupMenuAction implements IMouseAction {

                private final Menu menu;
                private final SelectionLayer selectionLayer;

                public CellPopupMenuAction(Menu menu, SelectionLayer selectionLayer) {
                    this.menu = menu;
                    this.selectionLayer = selectionLayer;
                }

                @Override
                public void run(NatTable natTable, MouseEvent event) 
                {
                    if( selectionLayer.getSelectedRowCount() <= 1 )
                            {
                                int colPosition = LayerUtil.convertColumnPosition( natTable,
                                        natTable.getColumnPositionByX( event.x ), selectionLayer );
                                int rowPosition = LayerUtil.convertRowPosition( natTable,
                                        natTable.getRowPositionByY( event.y ), selectionLayer );

                                natTable.doCommand( new SelectCellCommand( selectionLayer, colPosition, rowPosition, false,
                                        false ) );
                            }
                    menu.setData(event.data);
                    menu.setVisible(true);
                }
            }

我假设您在代码中将 selectionLayer 作为私有变量。

【讨论】:

  • 感谢选择销售,它完全符合我的要求。我已经查看了提供的链接,据我所知,它显示了有条件的菜单。但我需要根据条件在菜单中显示不同的项目。而且我仍然不知道如何实现这一目标
【解决方案3】:

我在上面使用了 SomeDude 的答案,它有效,但菜单项在选择之前显示,看起来很奇怪。我将菜单显示移动到 UI 线程 asyncExec 调用并首先发生选择,然后菜单出现在其顶部 -

@Override
public void run(NatTable natTable, MouseEvent event) {

    if (selectionLayer.getSelectedRowCount() <= 1) {

        int colPosition = LayerUtil.convertColumnPosition(natTable, natTable.getColumnPositionByX(event.x),
                selectionLayer);

        int rowPosition = LayerUtil.convertRowPosition(natTable, natTable.getRowPositionByY(event.y),
                selectionLayer);

        natTable.doCommand(new SelectCellCommand(selectionLayer, colPosition, rowPosition, false, false));

    }

    Display.getDefault().asyncExec(new Runnable() {
        public void run() {
            menu.setData(event.data);
            menu.setVisible(true);
        }
    });

}

【讨论】:

    猜你喜欢
    • 2018-07-02
    • 1970-01-01
    • 1970-01-01
    • 2017-04-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多