以编程方式禁用菜单项

4

我正在使用Netbeans RCP开发桌面应用程序。通过TopComponents中的注释,我添加了许多菜单项。我希望能够根据已登录用户的访问权限来禁用其中几个菜单项。


2
到目前为止,尽管这个问题在论坛上已经被问了很多次,但我还没有找到令人满意的解决方案。请提供前三个解决方案的链接并解释为什么它们不适用于您的用例。 - Andrew Thompson
https://www.google.de/search?q=disable+menu+at+runtime+netbeans+RCP,我查看了前三页,有几个死链接,一些明显没有回答,大多数与我的主题略有偏差。这个看起来很有希望:http://netbeans-org.1045718.n5.nabble.com/enable-disable-menubar-during-runtime-td3035568.html,但我还没有成功让它工作。 - Jannis Alexakis
2个回答

4
在NetBeans平台中,一种实现此功能的方式是在菜单中注册Presenter.Menu
@ActionID(id = "com.company.MyPresenter", category = "Edit")
@ActionRegistration(displayName = "com.company.Bundle#CTL_MyPresenter")
@ActionReference(path = "Menu/Edit", position = 1)
public class MyPresenter implements Presenter.Menu {

    @Override
    public JMenuItem getMenuPresenter() {
        // return menu item from your ACL'd registry
    }
}

当您在菜单中注册Presenter.Menu时,平台将调用getMenuPresenter()方法以获取实际添加到菜单中的JMenuItem
通常情况下,您只需在此处构造一个JMenuItem,但由于您需要能够在应用程序的其他部分中获得它,因此您需要保留某种菜单项注册表,以便在检索相同实例时使用。
一种方法是将所有ACL'd菜单项注册为ServiceProvider。通过这种方式,您可以在需要启用/禁用它们时Lookup所有这些菜单项。 ServiceProvider接口:
public interface ControllableMenuItem {

    void setEnabled(boolean enabled);

    JMenuItem getMenuItem();
}

一个作为ServiceProvider注册的ControllableMenuItem实现:

@ServiceProvider(service = ControllableMenuItem.class)
public class MyMenuItem implements ControllableMenuItem {

    private JMenuItem menuItem;

    @Override
    public void setEnabled(boolean enabled) {
        getMenuItem().setEnabled(enabled);
    }

    @Override
    public JMenuItem getMenuItem() {
        if (menuItem == null) {
            menuItem = new JMenuItem(new MyAction());
        }
        return menuItem;
    }
}

现在你可以在需要启用/禁用时查找所有的可控菜单项:

现在,当您需要启用/禁用菜单项时,您可以查找所有的可控制菜单项:

Collection<? extends ControllableMenuItem> menuItems = 
    Lookup.getDefault().lookupAll(ControllableMenuItem.class);
for (ControllableMenuItem item : menuItems) {
    item.setEnabled(isAuthorized());
}

然而,要使其正常工作还需要一个部分。您需要一种方法来保证Presenter.MenuLookup获取的是相同的实例。一种方法是将MenuItem注册为@ServiceProvider并在getMenuPresenter()中查找它,尽管这种方法不太优雅。
// replaces the above annotation of MyMenuItem
@ServiceProviders(value = {
    @ServiceProvider(service = ControllableMenuItem.class),
    @ServiceProvider(service = MyMenuItem.class)
})
public class MyMenuItem implements ControllableMenuItem {...}

public class MyPresenter implements Presenter.Menu {

    @Override
    public JMenuItem getMenuPresenter() {
        MyMenuItem myMenuItem = Lookup.getDefault().lookup(MyMenuItem.class);
        return myMenuItem.getMenuItem();
    }
}

以这种方式,每当你查找你的ControllableMenuItem时,可以确保获得相同的实例。
这只是一种方法。关键在于需要一个机制来获取所有需要禁用的ACL菜单项的相同实例。
控制哪些菜单项实际上进入菜单系统的另一种方法是为每个访问级别创建单独的模块,并在用户未获得特定功能组的授权时disable modules简单地禁用它们。这在许多方面都有益处,也是使用模块化系统的优点之一。

2

3
我建议您查看 ActionAbstractAction 类。 - Andrew Thompson
我熟悉xxx.setEnabled(boolean)和你提到的Swing组件。只是,菜单项是由Netbeans RCP(layer.xml)在启动时生成的,根据TopComponent类的注释。除非你知道一种调用这些生成的菜单项的方法,否则没有JMenus可供操作,这将确实回答我的问题。 - Jannis Alexakis
  1. 拒绝使用GUI生成器,手动创建JMenuBar、JMenu和JMenuItems。
  2. 必须为每个用户配置文件保留单独的JMenuItems数组。
  3. 采用非常疯狂的方式(从未在VBA、C/++或Java中使用任何GUI生成器),必须从JFrame派生JMenuBar及其Items,然后在JMenuItems内进行迭代。
- mKorbel
这就是我迄今为止一直在做的方式(您的第1点和第2点)。但是:我只想知道是否有任何使用RCP工具在运行时操作菜单项的方法。 - Jannis Alexakis
缺点(没有深入的知识,但这里永无止境的故事)是部分方法受保护,无法从方法中访问,因此您无法更改结果。出于这些原因,在GUI中的每个元素都有属性窗口,您必须在那里设置所需的方法或添加自定义代码块。很抱歉我不知道那是如何工作的。 - mKorbel

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