2013-01-11 27 views
1

我遇到了JTree和JButton的問題 這似乎是在進入編輯模式並將鼠標懸停在TreeCell上的按鈕上時,它渲染了按鈕內樹的某些部分。 即使在同一行中從一個按鈕拖動到另一個按鈕時,也會將另一個按鈕重新渲染到另一個按鈕上。JTree&JButtons - 當鼠標懸停在按鈕上時出現錯誤的渲染

這裏是一個短的Selfexplaining示例,你可以複製粘貼來看看我的意思。

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 Customizing中花了4天時間。但它真的讓我困惑,我怎麼能通過進入按鈕來停止渲染。

+2

use UIManager.getIcon(「OptionPane.errorIcon/informationIcon/warningIcon/questionIcon」);而不是在這裏編輯你的問題 – mKorbel

+2

也考慮一個[更簡單的例子](http://stackoverflow.com/a/4170233/230513)。 – trashgod

+2

可能是相關的或不相關的:編輯器實現無效 - 它_must_通知其聽衆終止編輯內部原因 – 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

相關問題