2016-11-30 72 views
3

我想爲0123reeJTree做一個自定義滾動效果。但是,我不確定如何針對單個句柄而不是所有句柄。添加滾動到JTree句柄

如果您運行下面的代碼,您會看到當您將鼠標懸停在JTree的任何句柄,節點或葉子上時,所有摺疊的句柄都將更改爲翻轉。這是不希望的。那麼當我將鼠標懸停在該句柄上時,如何更改只有一個句柄,並且最好不要將鼠標懸停在其旁邊的節點上?

import java.awt.*; 
import java.awt.event.*; 

import javax.swing.*; 
import javax.swing.tree.*; 
import javax.swing.plaf.basic.*; 

@SuppressWarnings("serial") 
public class DirectoryExplorer extends JFrame { 
    private DirectoryExplorer() { 
     super("Directory Explorer"); 
     setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
     setLayout(new GridLayout(1, 1)); 
     createPanel(); 
     setSize(800,600); 
     setVisible(true); 
    } 

    private void createPanel() { 
     JPanel panel = new JPanel(new GridLayout(1, 1)); 

     DefaultMutableTreeNode root = new DefaultMutableTreeNode("Hello"); 
     root.add(new DefaultMutableTreeNode("1")); 
     root.add(new DefaultMutableTreeNode("2")); 
     root.add(new DefaultMutableTreeNode("3")); 

     JTree tree = new JTree(); 
     BasicTreeUI tUI = (BasicTreeUI) tree.getUI(); 
     tUI.setCollapsedIcon(new ImageIcon("resources/closed.png")); 
     tUI.setExpandedIcon(new ImageIcon("resources/open.png")); 
     tree.setShowsRootHandles(true); 
     tree.addMouseMotionListener(new MouseHandler(tree)); 

     panel.add(new JScrollPane(tree)); 
     getContentPane().add(panel); 
    } 

    public static void main(String[] args) { 
     new DirectoryExplorer(); 
    } 

    private class MouseHandler implements MouseMotionListener { 
     JTree t = null; 
     BasicTreeUI tUI = null; 

     public MouseHandler(JTree tree) { 
      t = tree; 
      tUI = (BasicTreeUI) tree.getUI(); 
     } 

     @Override 
     public void mouseDragged(MouseEvent e) { 

     } 

     @Override 
     public void mouseMoved(MouseEvent e) { 
      TreePath selPath = t.getPathForLocation(e.getX(), e.getY()); 
      if(selPath != null) 
       tUI.setCollapsedIcon(new ImageIcon("resources/rollover.png")); 
      else 
       tUI.setCollapsedIcon(new ImageIcon("resources/closed.png")); 
      t.repaint(); 
     } 
    } 
} 
+0

「_DO你知道,如果有可能的目標個人把手當鼠標移動到他們嗎?_」我從來沒有嘗試過。 – trashgod

+1

根據猜測,您需要繼承「BasicTreeUI」。 – trashgod

+0

@trashgod你是對的。我可以通過創建'BasicTreeUI'的子類來實現,代碼如下,如果你感興趣 – Dan

回答

3

爲了達到你需要重寫BasicTreeUI.paintExpandControl()BasicTreeUI.MouseHandler.mouseMoved()期望的結果。您還需要創建幾個方法,例如setRolloverIcon()

工作示例可能看起來像這樣

import java.awt.Component; 
import java.awt.EventQueue; 
import java.awt.Graphics; 
import java.awt.GridLayout; 
import java.awt.Insets; 
import java.awt.Rectangle; 
import java.awt.event.MouseEvent; 
import java.net.MalformedURLException; 
import java.net.URL; 

import javax.swing.Icon; 
import javax.swing.ImageIcon; 
import javax.swing.JFrame; 
import javax.swing.JPanel; 
import javax.swing.JScrollPane; 
import javax.swing.JTree; 
import javax.swing.plaf.basic.BasicTreeUI; 
import javax.swing.tree.DefaultMutableTreeNode; 
import javax.swing.tree.TreePath; 

@SuppressWarnings("serial") 
public class DirectoryExplorer extends JFrame { 
    private DirectoryExplorer() { 
     super("Directory Explorer"); 
     setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
     setLayout(new GridLayout(1, 1)); 
     createPanel(); 
     setSize(800,600); 
     setVisible(true); 
    } 

    private void createPanel() { 
     JPanel panel = new JPanel(new GridLayout(1, 1)); 

     DefaultMutableTreeNode root = new DefaultMutableTreeNode("Hello"); 
     root.add(new DefaultMutableTreeNode("1")); 
     root.add(new DefaultMutableTreeNode("2")); 
     root.add(new DefaultMutableTreeNode("3")); 

     JTree tree = new JTree(); 

     //UI Stuff// 
     TreeHandleUI tUI = new TreeHandleUI(tree); 
     tree.setUI(tUI); 
     try { 
      tUI.setCollapsedIcon(new ImageIcon(new URL("https://i.stack.imgur.com/nKJFv.png"))); 
      tUI.setExpandedIcon(new ImageIcon(new URL("https://i.stack.imgur.com/NJvcp.png"))); 
      tUI.setRolloverIcon(new ImageIcon(new URL("https://i.stack.imgur.com/jN6uX.png"))); 
     } catch(MalformedURLException e) { 
      System.out.println("Bad URL/URLs"); 
     } 
     //////////// 

     tree.setShowsRootHandles(true); 

     panel.add(new JScrollPane(tree)); 
     getContentPane().add(panel); 
    } 

    public static void main(String[] args) { 
     EventQueue.invokeLater(() -> new DirectoryExplorer()); 
    } 

    private class TreeHandleUI extends BasicTreeUI { 
     ///Variables 
     private JTree t = null; 
     private Icon rolloverIcon = null; 
     private boolean rolloverEnabled = false; 
     private UpdateHandler uH = null; 

     private boolean isLeftToRight(Component c) { 
      return c.getComponentOrientation().isLeftToRight(); 
     } 

     public TreeHandleUI(JTree tree) { 
      t = tree; 
      uH = new UpdateHandler(t); 
      t.addMouseMotionListener(uH); 
     } 

     public void setRolloverIcon(Icon rolloverG) { 
      Icon oldValue = rolloverIcon; 
      rolloverIcon = rolloverG; 
      setRolloverEnabled(true); 
      if (rolloverIcon != oldValue) { 
       t.repaint(); 
      } 
     } 

     private void setRolloverEnabled(boolean handleRolloverEnabled) { 
      boolean oldValue = rolloverEnabled; 
      rolloverEnabled = handleRolloverEnabled; 
      if (handleRolloverEnabled != oldValue) { 
       t.repaint(); 
      } 
     } 

     @Override 
     protected void paintExpandControl(Graphics g, 
              Rectangle clipBounds, Insets insets, 
              Rectangle bounds, TreePath path, 
              int row, boolean isExpanded, 
              boolean hasBeenExpanded, 
              boolean isLeaf) { 
      Object value = path.getLastPathComponent(); 

      if (!isLeaf && (!hasBeenExpanded || treeModel.getChildCount(value) > 0)) { 
       int middleXOfKnob; 
       if (isLeftToRight(t)) { 
        middleXOfKnob = bounds.x - getRightChildIndent() + 1; 
       } else { 
        middleXOfKnob = bounds.x + bounds.width + getRightChildIndent() - 1; 
       } 
       int middleYOfKnob = bounds.y + (bounds.height/2); 

       if (isExpanded) { 
        Icon expandedIcon = getExpandedIcon(); 
        if(expandedIcon != null) 
         drawCentered(tree, g, expandedIcon, middleXOfKnob, middleYOfKnob); 
       } else if(isLocationInExpandControl(path, uH.getXPos(), uH.getYPos()) && !isExpanded && rolloverEnabled) { 
        if(row == uH.getRow()) { 
         if(rolloverIcon != null) 
          drawCentered(tree, g, rolloverIcon, middleXOfKnob, middleYOfKnob); 
        } else { 
         Icon collapsedIcon = getCollapsedIcon(); 
         if(collapsedIcon != null) 
          drawCentered(tree, g, collapsedIcon, middleXOfKnob, middleYOfKnob); 
        } 
       } else { 
        Icon collapsedIcon = getCollapsedIcon(); 
        if(collapsedIcon != null) 
         drawCentered(tree, g, collapsedIcon, middleXOfKnob, middleYOfKnob); 
       } 
      } 
     } 

     private class UpdateHandler extends BasicTreeUI.MouseHandler { 
      private JTree t = null; 
      private int xPos = 0; 
      private int yPos = 0; 

      private boolean leftToRight(Component c) { 
       return c.getComponentOrientation().isLeftToRight(); 
      } 

      public UpdateHandler(JTree tree) { 
       t = tree; 
      } 

      @Override 
      public void mouseMoved(MouseEvent e) { 
       xPos = e.getX(); 
       yPos = e.getY(); 
       t.repaint(); 
      } 

      public int getXPos() { 
       return xPos; 
      } 

      public int getYPos() { 
       return yPos; 
      } 

      public int getRow() { 
       return getRowForPath(t, getClosestPathForLocation(t, xPos, yPos)); 
      } 
     } 
    } 
} 

代碼將無需下載但是它們可用下面

closed.png
enter image description here

圖像運行open.png
enter image description here

rollover.png
enter image description here

+1

@trashgod好的,謝謝。我更新了我的答案,包括'EventQueue.invokeLater(() - > new DirectoryExplorer());' – Dan

+0

@trashgod如果你有時間我可以問你對代碼的想法是什麼? – Dan