2016-01-08 26 views
2

我需要幫助有關的JTree和JPopupMenu的靈氣行爲。我正在給JTree設置一個右鍵菜單。如果我打開右鍵菜單後,左鍵單擊一個節點與另一個節點,點擊節點成爲選擇。但在靈動的外觀和感覺上,需要第二次點擊來選擇另一個節點。我的代碼如下,你可以用默認的外觀和感覺來評論nimbus部分。改變靈氣JPopupMenu的行爲

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

[覆蓋JTree中的getPopupLocation](http://stackoverflow.com/a/8082241/714968),btw適用於Java 8和Nimbus L&F中的1.st鼠標事件。 – mKorbel

回答

2

如果打印出來的按下,釋放,單擊鼠標事件,你會看到與默認大號& f您得到

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

而隨着雨雲大號& 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 

這是雨雲的彈出窗口的期望的行爲,以消耗上接近該事件。 (見bug報告#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); 
     } 
    } 
} 
+0

非常感謝。它正在工作,但它正在改變我的應用程序中所有popup的行爲。有沒有辦法將它應用於只有一個Jtree或一個Popup。 – rdonuk

+1

@rdonuk由於這是不是每個組件的屬性,你要麼可以更改它顯示'JTree'(假定沒有其他彈出可以在同一時間顯示),或者你試試片斷我添加到我的答案之前。再次感謝 – SubOptimal

+0

,它工作得很好。 – rdonuk

0

有2個解決方案,你可以嘗試在不改變靈氣:

使用機器人類模擬第二次點擊。

添加到您的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適當的節點。