【问题标题】:Changing nimbus JPopupmenu behaviour改变 nimbus JPopupmenu 行为
【发布时间】:2016-01-08 14:19:29
【问题描述】:

我需要有关 JTree 和 JPopupMenu 的 nimbus 行为的帮助。我正在为 JTree 设置右键菜单。如果我在使用另一个节点打开右键菜单后左键单击一个节点,则单击的节点将被选中。但在 nimbus 外观和感觉中,选择另一个节点需要第二次单击。我的代码在下面,你可以用默认的外观和感觉来尝试它,并评论 nimbus 部分。

public class JTreeDemo {

    public static void main(String[] args) {

        try {
            for (LookAndFeelInfo info : UIManager.getInstalledLookAndFeels()) {
                if ("Nimbus".equals(info.getName())) {
                    UIManager.setLookAndFeel(info.getClassName());
                    break;
                }
            }
        } catch (Exception e) {
            try {
                UIManager.setLookAndFeel(UIManager.getCrossPlatformLookAndFeelClassName());
            } catch (Exception ex) {
            }
        }

        DefaultMutableTreeNode rootNode = new DefaultMutableTreeNode("Root");
        rootNode.add(new DefaultMutableTreeNode("Child1"));
        rootNode.add(new DefaultMutableTreeNode("Child2"));
        rootNode.add(new DefaultMutableTreeNode("Child3"));

        DefaultTreeModel model = new DefaultTreeModel(rootNode);

        JTree tree = new JTree(model);
        tree.addMouseListener(new TreeMouseListener());

        JFrame jf = new JFrame();
        jf.getContentPane().add(new JScrollPane(tree));

        jf.setSize(new Dimension(300, 300));

        jf.setVisible(true);
    }
}

class TreeMouseListener extends MouseAdapter {

    @Override
    public void mouseReleased(MouseEvent e) {
        if(SwingUtilities.isRightMouseButton(e)) {
            JTree tree = (JTree) e.getSource();

            TreePath jClickedPath = tree.getPathForLocation(e.getX(), e.getY());
            tree.setSelectionPath(jClickedPath);

            JPopupMenu menu = new JPopupMenu();
            menu.add(new JMenuItem("menu1"));
            menu.show(tree,  e.getX(), e.getY());
        }
    }
}

【问题讨论】:

标签: java swing nimbus


【解决方案1】:

如果您打印出按下、释放和单击的鼠标事件,您将看到使用默认 L&F 您会得到 ​​p>

// right click
tree: pressed
tree: released
tree: clicked
// click on node
tree: pressed
tree: released
tree: clicked

而使用 Nimbus L&F,您可以获得

// right click
tree: pressed
tree: released
tree: clicked
// first click on node, the pressed event is not passed to the listener
tree: released
tree: clicked
// second click on node
tree: pressed
tree: released
tree: clicked

这是 Nimbus 弹出窗口在关闭时消耗事件的期望行为。 (参见错误报告#JDK-6770445中的解释)

您可以在设置 L&F 后更改此行为。

UIManager.setLookAndFeel(info.getClassName());
UIManager.put("PopupMenu.consumeEventOnClose", false);

编辑片段以仅更改特定JTree的默认行为

// instruct the JTree not to close the popup
tree.putClientProperty("doNotCancelPopup",
    new JComboBox().getClientProperty("doNotCancelPopup"));

// create the popup menu not inside the listener
JPopupMenu popup = new JPopupMenu();
popup.add(new JMenuItem("menu1"));

// add the listener to the JTree
MouseListener popupListener = new PopupListener(popup);
tree.addMouseListener(popupListener);

以编程方式显示和隐藏弹出窗口

static class PopupListener extends MouseAdapter {

    JPopupMenu popup;

    PopupListener(JPopupMenu popupMenu) {
        popup = popupMenu;
    }

    @Override
    public void mousePressed(MouseEvent e) {
        togglePopup(e);
    }

    @Override
    public void mouseReleased(MouseEvent e) {
        togglePopup(e);
    }

    private void togglePopup(MouseEvent e) {
        if (e.isPopupTrigger()) {
            popup.show(e.getComponent(), e.getX(), e.getY());
        } else if (popup.isVisible()) {
            popup.setVisible(false);
        }
    }
}

【讨论】:

  • 非常感谢。它正在工作,但它正在改变我的应用程序中所有弹出窗口的行为。有没有办法将其仅应用于一个 Jtree 或一个 Popup。
  • @rdonuk 由于这不是每个组件的属性,您可以在显示 JTree 之前更改它(假设在同一时间不能显示其他弹出窗口)或者您尝试 sn -p 我添加到我的答案中。
【解决方案2】:

您可以在不更改 nimbus 的情况下尝试 2 种解决方案:

1. 使用 Robot 类模拟第二次点击。

将此添加到您的 MouseListener。

if(SwingUtilities.isLeftMouseButton(e) && e.getSource() instanceof JTree) {
            Robot bot = null;
            try {
                bot = new Robot();
            } catch (AWTException e1) {
                e1.printStackTrace();
            }
            bot.mousePress(InputEvent.BUTTON1_DOWN_MASK);
}

2. 添加TreeSelectionLisitener 和第一种方法一样使用 MouseListener 用 TreeSelectionListener 选择合适的节点。

【讨论】:

    猜你喜欢
    • 2012-07-22
    • 1970-01-01
    • 2012-12-18
    • 1970-01-01
    • 2012-01-09
    • 2022-01-23
    • 1970-01-01
    • 2016-07-10
    • 1970-01-01
    相关资源
    最近更新 更多