如何在 NetBeans 插件中创建动态菜单?
How to create dynamic menus in a NetBeans plugin?
我正在开发一个需要使用 "dynamic" 菜单的 NetBeans 插件,因为目前必须在专用于某个菜单项及其操作的 class 中进行硬编码。但是我希望允许用户通过插件提供的 UI 来更改菜单项的值(他们做什么 - 这将在 main 方法中处理变量,我不允许用户自己编写主要方法的代码——它们被调用的内容及其相关的键盘快捷键)以及添加和删除菜单项。我的插件可能会从一个文件中读取这些首选项,并且理想情况下只有一个 class 可以创建所有这些动态菜单项,它们的值在首选项文件中定义。
我知道有一种方法可以做到这一点,但我能在上面找到的唯一真实信息是 this thread and the bugzilla page 它链接到的链接目前似乎已关闭,所以这对我没有太大帮助...那么究竟怎样才能制作一个带有动态菜单项的动态菜单呢?
我有 NetBeans 8.1 版和 JDK8。此外,当我说 "dynamic menu item" 或类似内容时,我指的是从菜单中提供给您的实际选项(无论插件在那里做什么,在我的例子中,它都会将某些数据复制到剪贴板单击这些选项之一)。
我在 netbeans RCP 应用程序中使用动态菜单。以下是我用于将动态菜单项添加到右键单击菜单、工具栏、菜单栏...的一般格式...
import java.awt.event.ActionEvent;
import java.util.ArrayList;
import java.util.List;
import javax.swing.AbstractAction;
import javax.swing.Action;
import javax.swing.JComponent;
import javax.swing.JMenu;
import javax.swing.JMenuItem;
import javax.swing.JPopupMenu;
import javax.swing.JSeparator;
import org.openide.awt.ActionID;
import org.openide.awt.ActionReference;
import org.openide.awt.ActionReferences;
import org.openide.awt.ActionRegistration;
import org.openide.awt.Actions;
import org.openide.awt.DynamicMenuContent;
import org.openide.util.actions.Presenter;
/* Register your dynamic action using annotations (perferred over layer.xml entries)
@ActionID(id = "ExampleDynamicMenu", category = "Edit")
@ActionRegistration(lazy = false, displayName = "ExampleDynamicMenu")
@ActionReferences({
@ActionReference(path = "Loaders/folder/any/Actions", position = 666),
@ActionReference(path = "Loaders/content/unknown/Actions", position = 666),
@ActionReference(path = "Loaders/text/xml/Actions", position = 666),
@ActionReference(path = "Projects/Actions", position = 666),
@ActionReference(path = "Editors/TabActions", position = 666)
})
*/
public class ExampleDynamicMenu extends AbstractAction implements DynamicMenuContent, Presenter.Popup {
@Override
public JMenuItem getPopupPresenter() {
JMenu menu = new JMenu(this);
JComponent[] menuItems = createMenu();
for (JComponent item : menuItems) {
menu.add(item);
}
return menu;
}
@Override
public void actionPerformed(ActionEvent e) {
// does nothing, this is a popup menu
}
@Override
public JComponent[] getMenuPresenters() {
return createMenu();
}
@Override
public JComponent[] synchMenuPresenters(JComponent[] items) {
return createMenu();
}
private JComponent[] createMenu() {
List<JComponent> items = new ArrayList<>(20);
//TODO: Load the list of actions stored in the preferences, and for each action add a menu-item to the dynamic menu.
// Note: You preferences can simply store the Action's category and id; then you can always get the action instances using
// Action action = Actions.forID(category_string, id_string);
List<Action> actionsList = YOUR_PREFERENCES_GETTER.getActions(); //You have to figure out how to store and retrieve user's preferred actions list yourself :)
for (Action action : actionsList) {
if (action == null) { //Assume null means add a separator
if (items.size() > 0 && !(items.get(items.size() - 1) instanceof JSeparator)) { //Only add separators after actions.
items.add(new JPopupMenu.Separator());
}
} else { //Convert action to menu item, and build your dynamic menu
items.add(toMenuItem(action));
}
}
return items.toArray(new JComponent[items.size()]);
}
/**
* Creates a menu item from an action.
*
* @param action an action
* @return JMenuItem
*/
private static JMenuItem toMenuItem(Action action) {
JMenuItem item;
if (action instanceof Presenter.Menu) {
item = ((Presenter.Menu) action).getMenuPresenter();
} else if (action instanceof Presenter.Popup) {
item = ((Presenter.Popup) action).getPopupPresenter();
} else {
item = new JMenuItem();
Actions.connect(item, action, false);
}
return item;
}
}
我正在开发一个需要使用 "dynamic" 菜单的 NetBeans 插件,因为目前必须在专用于某个菜单项及其操作的 class 中进行硬编码。但是我希望允许用户通过插件提供的 UI 来更改菜单项的值(他们做什么 - 这将在 main 方法中处理变量,我不允许用户自己编写主要方法的代码——它们被调用的内容及其相关的键盘快捷键)以及添加和删除菜单项。我的插件可能会从一个文件中读取这些首选项,并且理想情况下只有一个 class 可以创建所有这些动态菜单项,它们的值在首选项文件中定义。
我知道有一种方法可以做到这一点,但我能在上面找到的唯一真实信息是 this thread and the bugzilla page 它链接到的链接目前似乎已关闭,所以这对我没有太大帮助...那么究竟怎样才能制作一个带有动态菜单项的动态菜单呢?
我有 NetBeans 8.1 版和 JDK8。此外,当我说 "dynamic menu item" 或类似内容时,我指的是从菜单中提供给您的实际选项(无论插件在那里做什么,在我的例子中,它都会将某些数据复制到剪贴板单击这些选项之一)。
我在 netbeans RCP 应用程序中使用动态菜单。以下是我用于将动态菜单项添加到右键单击菜单、工具栏、菜单栏...的一般格式...
import java.awt.event.ActionEvent;
import java.util.ArrayList;
import java.util.List;
import javax.swing.AbstractAction;
import javax.swing.Action;
import javax.swing.JComponent;
import javax.swing.JMenu;
import javax.swing.JMenuItem;
import javax.swing.JPopupMenu;
import javax.swing.JSeparator;
import org.openide.awt.ActionID;
import org.openide.awt.ActionReference;
import org.openide.awt.ActionReferences;
import org.openide.awt.ActionRegistration;
import org.openide.awt.Actions;
import org.openide.awt.DynamicMenuContent;
import org.openide.util.actions.Presenter;
/* Register your dynamic action using annotations (perferred over layer.xml entries)
@ActionID(id = "ExampleDynamicMenu", category = "Edit")
@ActionRegistration(lazy = false, displayName = "ExampleDynamicMenu")
@ActionReferences({
@ActionReference(path = "Loaders/folder/any/Actions", position = 666),
@ActionReference(path = "Loaders/content/unknown/Actions", position = 666),
@ActionReference(path = "Loaders/text/xml/Actions", position = 666),
@ActionReference(path = "Projects/Actions", position = 666),
@ActionReference(path = "Editors/TabActions", position = 666)
})
*/
public class ExampleDynamicMenu extends AbstractAction implements DynamicMenuContent, Presenter.Popup {
@Override
public JMenuItem getPopupPresenter() {
JMenu menu = new JMenu(this);
JComponent[] menuItems = createMenu();
for (JComponent item : menuItems) {
menu.add(item);
}
return menu;
}
@Override
public void actionPerformed(ActionEvent e) {
// does nothing, this is a popup menu
}
@Override
public JComponent[] getMenuPresenters() {
return createMenu();
}
@Override
public JComponent[] synchMenuPresenters(JComponent[] items) {
return createMenu();
}
private JComponent[] createMenu() {
List<JComponent> items = new ArrayList<>(20);
//TODO: Load the list of actions stored in the preferences, and for each action add a menu-item to the dynamic menu.
// Note: You preferences can simply store the Action's category and id; then you can always get the action instances using
// Action action = Actions.forID(category_string, id_string);
List<Action> actionsList = YOUR_PREFERENCES_GETTER.getActions(); //You have to figure out how to store and retrieve user's preferred actions list yourself :)
for (Action action : actionsList) {
if (action == null) { //Assume null means add a separator
if (items.size() > 0 && !(items.get(items.size() - 1) instanceof JSeparator)) { //Only add separators after actions.
items.add(new JPopupMenu.Separator());
}
} else { //Convert action to menu item, and build your dynamic menu
items.add(toMenuItem(action));
}
}
return items.toArray(new JComponent[items.size()]);
}
/**
* Creates a menu item from an action.
*
* @param action an action
* @return JMenuItem
*/
private static JMenuItem toMenuItem(Action action) {
JMenuItem item;
if (action instanceof Presenter.Menu) {
item = ((Presenter.Menu) action).getMenuPresenter();
} else if (action instanceof Presenter.Popup) {
item = ((Presenter.Popup) action).getPopupPresenter();
} else {
item = new JMenuItem();
Actions.connect(item, action, false);
}
return item;
}
}