2010-02-04 72 views
4

我使用CustomCellRenderer顯示一個JTree與節點作爲 顯示圖像的節點如下所示: -更改JTree的節點圖像動態

class CustomTreeCellRenderer extends DefaultTreeCellRenderer{ 

    public Component getTreeCellRendererComponent(JTree tree, 
     Object value, boolean selected, boolean expanded, 
     boolean leaf, int row, boolean hasFocus){ 

     super.getTreeCellRendererComponent(tree, value, 
     selected, expanded, leaf, row, hasFocus); 

     JLabel label = (JLabel) this ; 

     label.setIcon(new ImageIcon("white.png")) ; 

     return this; 
    } 
} 

我的要求是改變節點的圖像在一些外部行動。 我想重裝JTree的模型,但如下圖所示它不工作: -

public void actionPerformed(ActionEvent ae) { 

     DefaultTreeModel model = (DefaultTreeModel) tree.getModel() ; 

     JLabel label = (JLabel) tree.getCellRenderer() ; 
     System.out.println(label.getIcon()); //displaying white.png 

     label.setIcon(new ImageIcon("black.gif")) ; 


     model.reload() ; 
    } 

我哪裏做錯了??????

回答

1

將您的圖標添加到渲染器類中作爲字段。

更改此字段的值並重新繪製JTree。

class CustomTreeCellRenderer extends DefaultTreeCellRenderer{ 


    ImageIcon rendererIcon; 


    public void setRendererIcon(ImageIcon myIcon){ 
     this.rendererIcon = myIcon; 
    }; 


    public Component getTreeCellRendererComponent(JTree tree, 
     Object value, boolean selected, boolean expanded, 
     boolean leaf, int row, boolean hasFocus){ 

     super.getTreeCellRendererComponent(tree, value, 
     selected, expanded, leaf, row, hasFocus); 

     JLabel label = (JLabel) this ; 

     label.setIcon(rendererIcon) ; 

     return this; 
    } 
} 

編輯:解釋

在你的情況下,它是無用的改變模型。用於顯示每個節點的圖標是渲染器的一部分。

JTree的渲染器對象不被強制爲JComponent。當代碼調用getTreeCellRendererComponent時,它必須是提供JComponent的對象。

在你的情況,getCellRenderer的CAST()到一個JLabel只是普通的運氣,因爲DefaultTreeCellRenderer的默認實現的JLabel的延伸。

而事實上,由於您的渲染器自己調用了setIcon,所以getIcon方法爲您提供了放入渲染器的最後一個圖標是正常的。

的完整代碼的工作:

import java.awt.BorderLayout; 
import java.awt.Component; 
import java.awt.event.ActionEvent; 
import java.awt.event.ActionListener; 

import javax.swing.ImageIcon; 
import javax.swing.JButton; 
import javax.swing.JFrame; 
import javax.swing.JLabel; 
import javax.swing.JPanel; 
import javax.swing.JTree; 
import javax.swing.SwingUtilities; 
import javax.swing.tree.DefaultTreeCellRenderer; 

public class TestJTree { 

    private static ImageIcon iconWhite = new ImageIcon("white.jpg"); 

    private static ImageIcon iconBlack = new ImageIcon("black.jpg");; 

    public static void main(String[] args) { 
     TestJTree me = new TestJTree(); 
     me.process(); 
    } 

    private void process() { 
     SwingUtilities.invokeLater(new Runnable() { 

      public void run() { 
       initGui(); 

      } 

     }); 

    } 

    protected void initGui() { 
     JFrame frame = new JFrame("Test JTree"); 
     frame.setContentPane(new JPanel(new BorderLayout())); 

     final JTree tree = new JTree(); 
     frame.getContentPane().add(tree); 

     final CustomTreeCellRenderer renderer = new CustomTreeCellRenderer(); 
     renderer.setRendererIcon(iconWhite); 
     tree.setCellRenderer(renderer); 

     JPanel panelButtons = new JPanel(); 

     JButton buttonWhite = new JButton(""); 
     buttonWhite.setIcon(iconWhite); 
     JButton buttonBlack = new JButton(""); 
     buttonBlack.setIcon(iconBlack); 

     buttonBlack.addActionListener(new ActionListener(){ 

      public void actionPerformed(ActionEvent e) { 
       renderer.setRendererIcon(iconBlack); 
       tree.repaint(); 
      } 

     }); 

     panelButtons.add(buttonBlack); 
     panelButtons.add(buttonWhite); 
     frame.getContentPane().add(panelButtons,BorderLayout.SOUTH); 

     frame.setLocationRelativeTo(null); 
     frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
     frame.setSize(500,500); 
     frame.setVisible(true); 


    } 

    @SuppressWarnings("serial") 
    private static class CustomTreeCellRenderer extends DefaultTreeCellRenderer{ 


     ImageIcon rendererIcon; 


     public void setRendererIcon(ImageIcon myIcon){ 
      this.rendererIcon = myIcon; 
     }; 


     public Component getTreeCellRendererComponent(JTree tree, 
      Object value, boolean selected, boolean expanded, 
      boolean leaf, int row, boolean hasFocus){ 

      Component ret = super.getTreeCellRendererComponent(tree, value, 
      selected, expanded, leaf, row, hasFocus); 

      JLabel label = (JLabel) ret ; 

      label.setIcon(rendererIcon) ; 

      return ret; 
     } 
    } 
} 
+0

我已經試過了,但它不工作。 – mogli

+0

@rits 我添加的代碼正在爲我工​​作 –

+0

是的,它改變了整個樹的圖標,而不是選定的節點。 – mogli

1

幾個要點:

  1. 抓住從表中的方法渲染像actionPerformed並修改它是不常見的做法。您應該注意,渲染器是共享的,所以即使您在actionPerformed期間在渲染器實例上設置了Icon,也會影響該列中使用該渲染器的所有單元格
  2. ,但渲染器始終通過getTreeCellRendererComponent方法,並且你總是將圖標設置爲「white.png」,所以你永遠不會得到「black.gif」來顯示。

你有一個選擇是在你的actionPerformed方法的模型設定狀態,然後從getTreeCellRendererComponent內可以查詢你的模型的圖標顯示。

例如:

public void actionPerformed(ActionEvent ae) { 

    MyCustomTreeModel model = (MyCustomTreeModel) tree.getModel() ; 
    ... 
    model.setMyState(state); //set the state based on the action 
} 

中渲染:

public Component getTreeCellRendererComponent(JTree tree, 
    Object value, boolean selected, boolean expanded, 
    boolean leaf, int row, boolean hasFocus) 
{ 
    MyCustomTreeModel model = (MyCustomTreeModel) tree.getModel(); 
    .... 
    setIcon(model.getMyIconBasedOnTheStateISetInActionPerformed()); 
    return this;  
} 
+0

那麼該如何解決這個問題。用代碼解釋表示讚賞。 :) – mogli