2016-11-30 2 views
3

JTree의 Collapsed Icon에서 사용자 정의 롤오버 효과를 만들려고합니다. 그러나 모든 핸들 대신 개별 핸들을 대상으로 지정하는 방법을 잘 모르겠습니다.JTree 핸들에 롤오버 추가

아래 코드를 실행하면 JTree의 핸들, 노드 또는 리프 위로 마우스를 올려 놓으면 모든 접힌 핸들이 롤오버로 변경됩니다. 이것은 바람직하지 않습니다. 그렇다면 핸들 위에 마우스를 올려 놓을 때 단 하나의 핸들을 어떻게 바꿀 수 있습니까? 노드 옆에 마우스를 올려 놓을 때 핸들을 바꿀 필요가 없습니다. 당신이 BasicTreeUI.paintExpandControl()BasicTreeUI.MouseHandler.mouseMoved()를 재정의해야 원하는 결과를 달성하기 위해

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

을 시도 적이 rollover.png. – trashgod

+1

추측에, 당신은''BasicTreeUI'를 하위 클래스화할 필요가 있습니다. – trashgod

+0

@trashgod 당신 말이 맞았습니다. 나는'BasicTreeUI'의 서브 클래스를 생성함으로써 그것을 할 수있었습니다. 관심이 있다면 코드는 아래에 있습니다 – Dan

답변

3

. 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

는 "_do는 마우스가 그들 위에있을 때 각각의 핸들을 대상으로 할 수 있는지 알 수는? _"나는
enter image description here

+1

@trashgod 감사합니다. 'EventQueue.invokeLater (() -> new DirectoryExplorer());를 포함하도록 답변을 업데이트했습니다. – Dan

+0

@trashgod 잠시 시간이 있으면 코드에 어떤 의견이 있는지 물어볼 수 있습니까? – Dan