2009-02-05 19 views
27

Próbuję zaimplementować wyskakujące menu w Java JTree. Podkategorii DefaultTreeCellRenderer (aby zmienić wygląd węzła) i DefaultTreeCellEditor (aby utworzyć komponenty do dołączania detektorów zdarzeń do, ponieważ pozornie składniki, które DefaultTreeCellRenderer.getTreeCellRendererComponent() zwraca nie mogą tego zrobić?). Naprawdę nie chcę "edytować" węzłów, wystarczy, że wyskoczy do menu po kliknięciu prawym przyciskiem myszy, ale jest to jedyny sposób, w jaki mogę teraz to zrobić ...Kliknij prawym przyciskiem myszy menu kontekstowe Java JTree?

Poniżej znajduje się kod, który mam do tej pory - Po prostu próbuję dowiedzieć się, jak przechwycić MouseEvents. To działa, ale źle. Jaki jest lepszy sposób na zrealizowanie tego, co próbuję tutaj zrobić?

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; 
    } 
} 

Odpowiedz

1

renderer jest tylko przejściowy „pieczątka”, więc dodanie słuchacza naliczonego że przyzwyczajenie być szczególnie pomocne. Redaktor, jak zauważysz, jest tam tylko wtedy, gdy wykonałeś gesty do edycji. Więc chcesz dodać detektor do JTree (zakładając, że nie jest zaimplementowany jako komponent złożony).

20

Zrobione zaraz po wyjęciu z 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); 

Oczywiście trzeba zmodyfikować go trochę dla prawego kliknięcia zamiast lewego kliknięcia

2

myślę robisz rzeczy sposób trudniejsze niż muszą być.
JTree ma kilka metod "add_foo_Listener". Wdrożyć jedną z nich (TreeSelectionListener wygląda poprawnie), a następnie masz aktualnie wybrany węzeł.
Zaimplementuj MouseListener w taki sposób, aby można było wykryć zdarzenie uruchamiane prawym przyciskiem myszy (i dodać je do JTree, ponieważ JTree jest komponentem), a następnie powinieneś mieć wszystko, czego potrzebujesz, aby opublikować menu kontekstowe.
Aby uzyskać więcej informacji, zapoznaj się z tym tutorial.

12

Dziękuję wszystkim. Wiedziałem, że coś jest nie tak, kiedy tak dużo wysiłku wkładałem w wykonanie prostego popup.

Zlekceważyłem tę linię myślenia na początku, ponieważ czułem się dziwnie uciekać się do współrzędnych X i Y, aby znaleźć węzeł, którego szukam, ale myślę, że to jest sposób na zrobienie tego.

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

Za każdym razem tworzysz JPopupMenu. Przenieś kreację w inne miejsce, gdzie jest to zrobione tylko raz, zmodyfikuj ją na zdarzeniu –

+1

Jest to dobry przykład przedwczesnej optymalizacji (http://pl.wikiquote.org/wiki/Donald_Knuth). Tworzenie powolnego obiektu nie ma sensu, dopóki nie ma powodu, aby to zrobić (na przykład powolne inicjowanie zasobów). –

25

To zadanie jest proste do wykonania, po to wszystko, czego potrzebujesz:

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

Można następnie dodać ten niestandardowy słuchacza do wybranego drzewa (ów).

+2

+1 za adresowanie aspektu OP prawym przyciskiem myszy – amaidment

0

Zadzwoń pod numer addRightClickListener(), aby dodać detektor menu kontekstowego z prawym przyciskiem myszy do Twojego JTree. Oba przesłonięcia mają na celu odpowiednią funkcjonalność między platformami (Windows i Linux różnią się tutaj).

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()); 
    } 
} 
Powiązane problemy