2013-01-11 3 views
1

JTree 및 JButton에 문제가 있습니다 편집 모드에 들어가서 TreeCell의 단추 위로 마우스를 가져 가면 단추 내부의 일부 트리가 Renderes됩니다 . 동일한 행의 한 단추에서 다른 단추로 끌면 다른 단추보다 한 단추가 Renderes됩니다.JTree & JButtons - 마우스가 단추 위로 움직일 때 잘못된 렌더링이 발생했습니다.

여기에 붙여 넣기를 복사 할 수있는 간단한 자기 설명 샘플. 의미를 확인하십시오.

import java.awt.Color; 
import java.awt.Component; 
import java.awt.Dimension; 
import java.awt.FlowLayout; 
import java.awt.event.ActionEvent; 
import java.awt.event.ActionListener; 
import java.awt.event.MouseEvent; 
import java.awt.event.MouseMotionListener; 
import java.util.EventObject; 

import javax.swing.JButton; 
import javax.swing.JFrame; 
import javax.swing.JLabel; 
import javax.swing.JPanel; 
import javax.swing.JScrollPane; 
import javax.swing.JTree; 
import javax.swing.UIManager; 
import javax.swing.tree.DefaultMutableTreeNode; 
import javax.swing.tree.DefaultTreeCellEditor; 
import javax.swing.tree.DefaultTreeCellRenderer; 


public class MyProblemWithTree { 

    public static void main(String...args) { 
     JFrame frame = new JFrame("Panel"); 
     JScrollPane scroll = new JScrollPane(); 

     DefaultMutableTreeNode node = new DefaultMutableTreeNode("Root"); 

     DefaultMutableTreeNode nodeChild = new DefaultMutableTreeNode("childcaretaker1"); 
     nodeChild.add(new DefaultMutableTreeNode("child1")); 
     nodeChild.add(new DefaultMutableTreeNode("child2")); 

     node.add(nodeChild); 


     final JTree tree = new JTree(node); 

     tree.setCellRenderer(new MyTreeCellRenderer()); 
     tree.setEditable(true); 
     tree.setCellEditor(new MyTreeCellEditor(tree)); 

     tree.addMouseMotionListener(new MouseMotionListener() { 

      @Override 
      public void mouseMoved(MouseEvent e) { 
       // TODO Auto-generated method stub 
       if (tree.getRowForLocation(e.getX(), e.getY()) != -1) 
       { 
        tree.startEditingAtPath(tree.getPathForLocation(e.getX(), e.getY())); 
       } 
      } 

      @Override 
      public void mouseDragged(MouseEvent arg0) { 
       // TODO Auto-generated method stub 

      } 
     }); 

     scroll.setViewportView(tree); 
     frame.add(scroll); 
     frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
     frame.pack(); 
     frame.setVisible(true); 
    } 
} 
class MyTreeCellEditor extends DefaultTreeCellEditor { 

    JPanel  leafPanel; 
    JLabel  colorIcon; 
    PlayButton play; 
    PauseButton pause; 
    JLabel  name; 

    public MyTreeCellEditor(JTree tree) { 
     super(tree, (MyTreeCellRenderer)tree.getCellRenderer()); 
     leafPanel = new JPanel(new FlowLayout()); 
     colorIcon = new JLabel(UIManager.getIcon("OptionPane.informationIcon")); 
     play  = new PlayButton(); 
     pause  = new PauseButton(); 
     name  = new JLabel(); 

     play.addActionListener(new ActionListener() { 

      @Override 
      public void actionPerformed(ActionEvent arg0) { 
       // TODO Auto-generated method stub 
       System.out.println("Playbutton klickt"); 
      } 
     }); 

     leafPanel.add(colorIcon); 
     leafPanel.add(name); 
     leafPanel.add(pause); 
     leafPanel.add(play); 
    } 


    @Override 
    public Component getTreeCellEditorComponent(JTree tree, Object value, 
      boolean selected, boolean expanded, boolean leaf, int row) { 

     name.setText((String)((DefaultMutableTreeNode)value).getUserObject()); 
     pause.setVisible(!leaf); 
     return leafPanel; 
    } 

    @Override 
    public boolean isCellEditable(EventObject arg0) { 
     return true; 
    } 
} 
class MyTreeCellRenderer extends DefaultTreeCellRenderer { 
    private static final long serialVersionUID = 3691823996133806942L; 

    JPanel leafPanel; 
    JLabel colorIcon; 
    PlayButton play; 
    PauseButton pause; 
    JLabel name; 

    DefaultTreeCellRenderer defaultRenderer = new DefaultTreeCellRenderer(); 

    Color backgroundSelectionColor; 
    Color backgroundNonSelectionColor; 


    public MyTreeCellRenderer() { 
     leafPanel = new JPanel(new FlowLayout()); 
     colorIcon = new JLabel(UIManager.getIcon("OptionPane.informationIcon")); 
     play = new PlayButton(); 
     pause = new PauseButton(); 
     name = new JLabel(); 

     leafPanel.add(colorIcon); 
     leafPanel.add(name); 
     leafPanel.add(pause); 
     leafPanel.add(play); 

     backgroundSelectionColor = new Color(200,200,255,50); 
     backgroundNonSelectionColor = new Color(0,0,0,0); 
    } 

    @Override 
    public Component getTreeCellRendererComponent(JTree tree, Object value, boolean selected, boolean expanded, boolean leaf, int row, boolean hasFocus) { 
     name.setText((String)((DefaultMutableTreeNode) value).getUserObject()); 
     if (selected) { 
      leafPanel.setBackground(backgroundSelectionColor); 
     } else { 
      leafPanel.setBackground(backgroundNonSelectionColor);      
     } 
     leafPanel.setEnabled(tree.isEnabled()); 
     pause.setVisible(!leaf); 
     return leafPanel; 
    } 
} 

class PlayButton extends JButton{ 
    private static final long serialVersionUID = 550654173835539853L; 

    Dimension size = new Dimension(140,28); 

    public PlayButton() { 
     setIcon(UIManager.getIcon("OptionPane.informationIcon")); 
     setPressedIcon(UIManager.getIcon("OptionPane.errorIcon")); 
     setBackground(new Color(0,0,0,0)); 
     setBorderPainted(false); 
     setPreferredSize(size); 
     setMaximumSize(size); 
     setMinimumSize(size); 
    } 
} 
class PauseButton extends JButton{ 
    private static final long serialVersionUID = -5877843953696256070L; 

    Dimension size = new Dimension(140,28); 

    public PauseButton() { 
     setIcon(UIManager.getIcon("OptionPane.warningIcon")); 
     setPressedIcon(UIManager.getIcon("OptionPane.questionIcon")); 
     setBackground(new Color(0,0,0,0)); 
     setBorderPainted(false); 
     setPreferredSize(size); 
     setMaximumSize(size); 
     setMinimumSize(size); 
    } 
} 

이 부분을 지울 때도. 편집 모드를 시작하려면 셀을 클릭해야합니다. 셀을 마우스로두고 다시 돌아가서 효과를 얻을 수 있습니다.

 public void mouseMoved(MouseEvent e) { 
      // TODO Auto-generated method stub 
      if (tree.getRowForLocation(e.getX(), e.getY()) != -1) 
      { 
       tree.startEditingAtPath(tree.getPathForLocation(e.getX(), e.getY())); 
      } 
     } 

나는이 JTree 커스터마이징에 이미 4 일을 소비합니다. 하지만 실제로는 혼란 스럽습니다. 버튼 입력으로 렌더링을 멈출 수있는 방법입니다.

+2

사용 UIManager.getIcon ("OptionPane.errorIcon/informationIcon/warningIcon/questionIcon"); 대신 여기에 귀하의 질문을 편집 – mKorbel

+2

[간단한 예제] (http://stackoverflow.com/a/4170233/230513) 고려하십시오. – trashgod

+2

과 관련이있을 수도 있고 그렇지 않을 수도 있습니다. 편집기 구현이 유효하지 않습니다. 내부 원인에 따라 편집을 종료 할 때 리스너에게 통지해야합니다. – kleopatra

답변

1

이 문제를 해결하는 방법을 모르겠지만 invokeLatersetRowHeight()을 사용하는 것이 좋습니다.

public static void main(String... args) { 
    EventQueue.invokeLater(new Runnable() { 

     @Override 
     public void run() { 
      JFrame frame = new JFrame("Panel"); 
      ... 
      tree.setRowHeight(icon.getIconHeight()); 
      ... 
      frame.setVisible(true); 
     } 
    }); 
} 
+0

안녕하세요 @ Catalina 섬 invokeLater과 높이를 설정 내 메인 코드를 둘러싸고했지만, 그것은 문제를 해결하지 못했습니다. 그것을 시도하고 효과가 있었습니까? 그게 사실이라면, 내가 쓴 것을 실수로 어디서했는지 말하라. 숨어있는 물건은 단지 여기에서 간단히하기 때문에 내 문제를 해결하지 못합니다. 그래서 높이와 너비가 변하는 것이 도움이됩니다. 버튼에 렌더링 된 셀이라는 것을 볼 수 있도록 버튼을 의도적으로 만들었습니다. – Sven

+0

@Sven :'invokeLater'는 "버튼 내부 트리의 일부분"을 보여주지 못했을 것입니다. 관계없이; 'setRowHeight'는 아이콘을 위아래에 덜 잘립니다. 솔직히 나무에서 버튼을 피하려고 노력하지만 클레오 파트라의 방법을 시도해 볼 수도 있습니다. –

+0

나는 내가 무언가를 발견했다고 생각하지만 다음 주 이전에 확신 할 수 없다. 다른 PC에서는 이상한 렌더링이 나타나지 않았습니다. 그래서 직장에서 사용한 jdk를 바꿔서 문제가 해결되는지 살펴 보겠습니다. 집에서 그것을 재현 할 수 없다. – Sven