29

JavaJTreeにポップアップメニューを実装しようとしています。DefaultTreeCellRenderer(ノードの外観を変更するため)とDefaultTreeCellEditor(イベントリスナーをアタッチするコンポーネントを作成するため)をサブクラス化しました。これは、DefaultTreeCellRenderer.getTreeCellRendererComponent()が返すコンポーネントではできないためです)。ノードを「編集」したくはありません。ノードが右クリックされたときにメニューをポップアップできるようにするだけですが、これが今私が考えることができる唯一の方法です...

以下は私がこれまでに持っているコードです-私は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's 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;
    }
}
4

6 に答える 6

32

このタスクは簡単に実行できます。必要なものは次のとおりです。

//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());
    }
}

その後、このカスタム リスナーを目的のツリーに追加できます。

于 2012-06-02T03:35:40.340 に答える
20

JTreeAPIから直接取得

 // 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);

もちろん、左クリックではなく右クリック用に少し変更する必要があります

于 2009-02-05T23:45:23.460 に答える
2

あなたは物事を必要以上に難しくしていると思います。
JTreeには、いくつかの「add_foo_Listener」メソッドがあります。それらの1つを実装すると(TreeSelectionListenerはほぼ正しく見えます)、現在選択されているノードが得られます。
右クリックイベントを検出できるようにMouseListenerを実装すると(JTreeはコンポーネントであるため、JTreeに追加できます)、コンテキスト依存メニューを投稿するために必要なものがすべて揃っているはずです。
詳細については、このチュートリアルを確認してください。

于 2009-02-05T23:56:16.793 に答える
1

レンダラーは一時的な「ラバースタンプ」にすぎないため、その上に入力リスナーを追加しても特に役立ちません。ご指摘のとおり、エディターは、編集するためのジェスチャーを行った後にのみ存在します。したがって、リスナーをJTreeに追加する必要があります(複合コンポーネントとして実装されていない場合)。

于 2009-02-05T20:20:50.160 に答える