目前我的程序有一个动态构建的JTree
菜单。我向菜单构建器传递一个对象,该对象用一个字符串数组描述它的路径,其中每个元素代表一个节点,然后设置最后一个节点来调用该对象的方法。只有在新节点不存在的情况下才会创建新节点,否则将检查子菜单并重复整个过程。
我正在尝试将其切换到JMenu
系统而不是树,但我遇到了一些问题。
因此,例如,字符串数组看起来像:
["New", "Job", "Item A"]
["New", "Job", "Item B"]
["New", "Search", "Item C"]
然后,这将创建一个树,如:
┬ New
├──┬ Job
│ ├── Item A
│ └── Item B
└──┬ Search
└── Item C
现在我遇到的问题是我无法判断一个子菜单是否已存在JMenu
。如何检查是否已存在具有所需名称的子菜单?
以下是我如何构建JTree
:
String[] nodeNames = pane.getNodeDirectory();
MenuTreeNode targetNode = root;
int i = 0;
if(targetNode.getChildCount() > 0) {
//Search for the first node that doesn't exist in the pane's directory
for(; i < nodeNames.length; ++i) {
Enumeration e = targetNode.children();
while(e.hasMoreElements()) {
MenuTreeNode node = (MenuTreeNode)e.nextElement();
if(node.getName().equals(nodeNames[i])) {
targetNode = node;
break;
}
}
//We've been over all the children and none matched so we need
//to build the rest of the directory.
if(!e.hasMoreElements()) {
++i;
break;
}
}
}
//Build the remainder of the pane's directory
for(; i < nodeNames.length; ++i) {
MenuTreeNode currentNode = new MenuTreeNode(nodeNames[i]);
targetNode.add(currentNode);
targetNode = currentNode;
}
targetNode.setContentPane(pane);
model.nodeStructureChanged(root);
答案 0 :(得分:0)
好的,我想出了这个。它没有经过详尽的测试,但似乎有效。
获取菜单或菜单项名称的方法是通过Accessible
界面。我假设所有分支都是JMenu
类型。我不确定假设是多么安全。
String[] nodeNames = pane.getNodeDirectory();
JMenu currentMenu = null;
int i = 0;
for(int m = 0; m < menuBar.getMenuCount(); ++m) {
String name = menuBar.getMenu(m).getAccessibleContext().getAccessibleName();
if(name.equals(nodeNames[i])) {
currentMenu = menuBar.getMenu(m);
break;
}
}
++i;
if(currentMenu != null && currentMenu.getMenuComponentCount() > 0) {
boolean startBuild = false;
//Find the first non existant child
for(; i < nodeNames.length; ++i) {
for(int j = 0; j < currentMenu.getMenuComponentCount(); ++j) {
Component c = currentMenu.getMenuComponent(j);
//If we're not at the leaf node search for a JMenu and if it
//has the correct name set it as the current menu and move
//onto the next node.
if(i < nodeNames.length - 1 && c instanceof JMenu) {
String name = ((Accessible)c).getAccessibleContext().getAccessibleName();
if(name.equals(nodeNames[i])) {
currentMenu = (JMenu)c;
break;
}
//If we're at the leaf node search for a JMenuItem to make
//sure the requested item doesn't already exist
} else if(i == nodeNames.length - 1 && c instanceof JMenuItem) {
String name = ((Accessible)c).getAccessibleContext().getAccessibleName();
if(name.equals(nodeNames[i])) {
return;
}
}
//If we've reached the last component without finding an
//appropriate item start building the menu
if(j == currentMenu.getMenuComponentCount() - 1) {
startBuild = true;
}
}
if(startBuild) {
break;
}
}
} else if(currentMenu == null) {
currentMenu = new JMenu(nodeNames[i]);
menuBar.add(currentMenu);
}
//Continue the loop from where we left off but this time making the
//missing nodes instead of searching for existing nodes.
for(; i < nodeNames.length - 1; ++i) {
JMenu newMenu = new JMenu(nodeNames[i]);
currentMenu.add(newMenu);
currentMenu = newMenu;
}
JMenuItem item = new JMenuItem(nodeNames[nodeNames.length - 1]);
item.addActionListener(new ActionListener() {
@Override public void actionPerformed(ActionEvent e) {
pane.giveFocus();
}
});
currentMenu.add(item);
答案 1 :(得分:0)
您可以混合使用一些不同的方法调用和类型检查来完成此任务。
以下代码动态构建菜单,丢弃重复项。
public static void main(String[] args) {
// just example input
String[][] menuHierarchies = {
{"New", "Job", "Item A"},
{"New", "Job", "Item B"},
{"New", "Search", "Item C"},
{"New", "Item D"},
{"Other", "Item E"},
{"New", "Job", "Item B"},
{"Other", "Job", "Item B"}
};
JMenuBar menuBar = new JMenuBar();
// relevant code from here. It builds the menu removing redundancies
for (int rootIndex = 0; rootIndex < menuHierarchies.length; ++rootIndex) {
JMenu parentMenu = null;
for(int menuLevel = 0; menuLevel < menuHierarchies[rootIndex].length; ++menuLevel) {
// if it is root menu
if (menuLevel == 0) {
// checks if the root menu already exists
for (int i = 0; i < menuBar.getMenuCount(); ++i) {
if (menuBar.getMenu(i).getText().equals(menuHierarchies[rootIndex][menuLevel])) {
parentMenu = menuBar.getMenu(i);
break;
}
}
if (parentMenu == null) {
parentMenu = new JMenu(menuHierarchies[rootIndex][menuLevel]);
menuBar.add(parentMenu);
}
} else if (menuLevel < menuHierarchies[rootIndex].length - 1) { // if it is a non-leaf (and, of course, not a root menu)
Component[] menuComponents = parentMenu.getMenuComponents();
JMenu currentMenu = null;
// checks if the menu already exists
for (Component component : menuComponents) {
if (component instanceof JMenu) {
if (((JMenu) component).getText().equals(menuHierarchies[rootIndex][menuLevel])) {
currentMenu = (JMenu) component;
break;
}
}
}
if (currentMenu == null) {
currentMenu = new JMenu(menuHierarchies[rootIndex][menuLevel]);
parentMenu.add(currentMenu);
}
parentMenu = currentMenu;
} else { // if it is a leaf
Component[] menuComponents = parentMenu.getMenuComponents();
JMenuItem currentItem = null;
for (Component component : menuComponents) {
if (component instanceof JMenuItem) {
if (((JMenuItem) component).getText().equals(menuHierarchies[rootIndex][menuLevel])) {
currentItem = (JMenuItem) component;
break;
}
}
}
if (currentItem == null) {
parentMenu.add(new JMenuItem(menuHierarchies[rootIndex][menuLevel]));
}
}
}
}
}
以下方法打印构建的菜单层次结构,用于测试目的:
private static void printMenu(JMenuBar menuBar) {
for (int i = 0; i < menuBar.getMenuCount(); ++i) {
printMenu(menuBar.getMenu(i), 0);
}
}
private static void printMenu(JMenuItem menuItem, int level) {
for (int i = 0; i < level; ++i) {
System.out.print("\t");
}
System.out.println("\\" + menuItem.getText());
if (menuItem instanceof JMenu) {
JMenu menu = (JMenu) menuItem;
Component[] menuComponents = menu.getMenuComponents();
for (Component component : menuComponents) {
if (component instanceof JMenuItem) {
printMenu((JMenuItem) component, level+1);
}
}
}
}