2010-02-04 74 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