Подтвердить что ты не робот

Щелкните контекстное меню правой кнопки мыши для Java JTree?

Я пытаюсь реализовать всплывающие меню в Java JTree. Я подклассифицировал DefaultTreeCellRenderer (чтобы изменить внешний вид node) и DefaultTreeCellEditor (для создания компонентов для присоединения прослушивателей событий, поскольку, по-видимому, Компоненты, возвращаемые DefaultTreeCellRenderer.getTreeCellRendererComponent(), не могут это сделать?). Я действительно не хочу "редактировать" узлы, просто смогу всплывать меню, когда node получает щелчок правой кнопкой мыши, но это единственный способ, которым я могу сейчас это сделать...

Ниже приведен код, который у меня есть до сих пор. Я просто пытаюсь понять, как захватить MouseEvents. Это вроде работы, но плохо. Какой лучший способ выполнить то, что я пытаюсь сделать здесь?

private class My_TreeCellRenderer extends DefaultTreeCellRenderer { 
    My_TreeCellRenderer() {
        super ();
    }   

    public Component getTreeCellRendererComponent(JTree tree, Object value, boolean selected, boolean expanded, boolean leaf, int row, boolean hasFocus) {
        super.getTreeCellRendererComponent(tree, value, selected, expanded, leaf, row, hasFocus);

        // set label text and tool tips
        setText(((My_Object)value).getTreeLabel());
        setToolTipText(((My_Object)value).getTreeToolTip());

        return this;
    }
}

private class My_TreeCellEditor extends DefaultTreeCellEditor { 
    private MouseAdapter ma;

    My_TreeCellEditor(JTree tree, DefaultTreeCellRenderer renderer) {
        super (tree, renderer);
        ma = new MouseAdapter() {
            public void mousePressed(MouseEvent e) {
                if (e.isPopupTrigger()) {
                    System.out.println("My Popup");
                }
            }
            public void mouseReleased(MouseEvent e) {
                if (e.isPopupTrigger()) {
                    System.out.println("My Popup");
                }
            }
        };
    }

    public Component getTreeCellEditorComponent(JTree tree, Object value, boolean selected, boolean expanded, boolean leaf, int row) {
        String src_filename = null;

        // return non-editing component
        Component c = renderer.getTreeCellRendererComponent(tree, value, selected, expanded, leaf, row, true);

        // add mouse listener if it not listening already
        MouseListener mouseListeners[] = c.getMouseListeners();
        int i;
        for (i=0; i < mouseListeners.length && mouseListeners[i] != ma; i++);
        if (i >= mouseListeners.length)
            c.addMouseListener(ma);

        return c;
    }

    protected boolean canEditImmediately(EventObject event) {
        if (event instanceof MouseEvent && ((MouseEvent)event).getClickCount() == 1)
            return true;
        else
            return false;
    }
}
4b9b3361

Ответ 1

Эта задача проста для выполнения, вам нужно следующее:

//create a class which implements the MouseListener interface and
//implement the following in your overridden mouseClicked method

@Override
public void mouseClicked(MouseEvent e) {

    if (SwingUtilities.isRightMouseButton(e)) {

        int row = tree.getClosestRowForLocation(e.getX(), e.getY());
        tree.setSelectionRow(row);
        popupMenu.show(e.getComponent(), e.getX(), e.getY());
    }
}

Затем вы можете добавить этот пользовательский прослушиватель в нужное дерево (ы).

Ответ 2

Взято прямо из JTree API

 // If you are interested in detecting either double-click events or when a user clicks on a node, regardless of whether or not it was selected, we recommend you do the following:

 final JTree tree = ...;

 MouseListener ml = new MouseAdapter() {
     public void mousePressed(MouseEvent e) {
         int selRow = tree.getRowForLocation(e.getX(), e.getY());
         TreePath selPath = tree.getPathForLocation(e.getX(), e.getY());
         if(selRow != -1) {
             if(e.getClickCount() == 1) {
                 mySingleClick(selRow, selPath);
             }
             else if(e.getClickCount() == 2) {
                 myDoubleClick(selRow, selPath);
             }
         }
     }
 };
 tree.addMouseListener(ml);

Конечно, вам нужно немного изменить его для правого клика, а не щелкнуть левой кнопкой мыши

Ответ 3

Спасибо всем. Я знал, что что-то не так, когда я тратил столько усилий на реализацию простого всплывающего окна.

Сначала я отклонил эту мысль, потому что мне было странно прибегать к координатам x и y, чтобы найти node, который я ищу, но я думаю, что это способ сделать это.

    // add MouseListener to tree
    MouseAdapter ma = new MouseAdapter() {
        private void myPopupEvent(MouseEvent e) {
            int x = e.getX();
            int y = e.getY();
            JTree tree = (JTree)e.getSource();
            TreePath path = tree.getPathForLocation(x, y);
            if (path == null)
                return; 

            tree.setSelectionPath(path);

            My_Obj obj = (My_Obj)path.getLastPathComponent();

            String label = "popup: " + obj.getTreeLabel();
            JPopupMenu popup = new JPopupMenu();
            popup.add(new JMenuItem(label));
            popup.show(tree, x, y);
        }
        public void mousePressed(MouseEvent e) {
            if (e.isPopupTrigger()) myPopupEvent(e);
        }
        public void mouseReleased(MouseEvent e) {
            if (e.isPopupTrigger()) myPopupEvent(e);
        }
    };

    (...)

    JTree tree = new JTree();
    tree.addMouseListener(ma);

Ответ 4

Я думаю, вы делаете все намного сложнее, чем нужно. JTree имеет несколько методов "add_foo_Listener". Внесите один из них (TreeSelectionListener выглядит правильно), а затем у вас есть выбранный node.
Внесите MouseListener, чтобы вы могли обнаружить событие щелчка правой кнопкой мыши (и добавить его в JTree, так как JTree Component), а затем у вас должно быть все, что вам нужно, чтобы публиковать контекстно-зависимое меню.
Подробнее см. tutorial.

Ответ 5

Renderer - это только временная "резиновая штамп", поэтому добавление слушателя ввода на этом не является особенно полезным. Редактор, как вы указываете, доступен только после того, как вы указали на редактирование. Таким образом, вы хотите добавить слушателя в JTree (предполагая, что он не реализован как составной компонент).

Ответ 6

Вызовите addRightClickListener(), чтобы добавить прослушиватель контекстного меню правой кнопкой мыши к вашему JTree. Оба переопределения предназначены для правильной межплатформенной функциональности (Windows и Linux здесь отличаются).

private void addRightClickListener()
{
    MouseListener mouseListener = new MouseAdapter()
    {
        @Override
        public void mousePressed(MouseEvent mouseEvent)
        {
            handleContextMenu(mouseEvent);
        }

        @Override
        public void mouseReleased(MouseEvent mouseEvent)
        {
            handleContextMenu(mouseEvent);
        }
    };

    tree.addMouseListener(mouseListener);
}

private void handleContextMenu(MouseEvent mouseEvent)
{
    if (mouseEvent.isPopupTrigger())
    {
        MyContextMenu contextMenu = new MyContextMenu();

        contextMenu.show(mouseEvent.getComponent(),
                mouseEvent.getX(),
                mouseEvent.getY());
    }
}