2016-11-30 3 views
3

Ich versuche, einen benutzerdefinierten Rollover-Effekt für einen JTree Collapsed Icon zu machen. Ich bin mir jedoch nicht sicher, wie ich ein einzelnes Handle statt aller Handles anvisieren soll.Hinzufügen von Rollover zu JTree-Handles

Wenn Sie den unten stehenden Code ausführen, werden Sie sehen, dass alle ausgeblendeten Griffe in den Rollover umgewandelt werden, wenn Sie den Mauszeiger über ein Handle, einen Knoten oder ein Blatt des JTree bewegen. Dies ist nicht erwünscht. Wie kann ich also nur einen einzigen Ziehpunkt ändern, wenn ich über diesen Ziehpunkt schwebe, und vorzugsweise nicht, wenn ich den Knoten daneben bewege?

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 Sie wissen, ob es möglich ist, einzelne Griffe zum Ziel, wenn die Maus über sie ist? _“ Ich habe noch nie versucht. – trashgod

+1

Bei einer Schätzung müssten Sie "BasicTreeUI" ableiten. – trashgod

+0

@trashgod Du hattest Recht. Ich konnte es tun, indem ich eine Unterklasse von 'BasicTreeUI' erstellte, Code ist unten, wenn Sie interessiert sind – Dan

Antwort

3

Um das gewünschte Ergebnis, das Sie BasicTreeUI.paintExpandControl() und BasicTreeUI.MouseHandler.mouseMoved() außer Kraft setzen müssen zu erreichen. Sie müssen auch einige Methoden wie setRolloverIcon() erstellen.

Ein Arbeits Beispiel hierfür könnte wie folgt aussehen

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

-Code ohne das Herunterladen von Bildern laufen aber sie unter verfügbar sind

closed.png
enter image description here

open.png
enter image description here

rollover.png
enter image description here

+1

@trashgod Okay danke. Ich habe meine Antwort aktualisiert, um 'EventQueue.invokeLater (() -> new DirectoryExplorer());' – Dan

+0

@trashgod Wenn Sie einen Moment haben, wäre ich in der Lage zu fragen, was Ihre Gedanken über den Code sind? – Dan