Java 动态更改JTree的节点映像

Java 动态更改JTree的节点映像,java,swing,jtree,Java,Swing,Jtree,我正在使用CustomCellRenderer显示JTree的节点,以显示节点为的图像 如下所示:- class CustomTreeCellRenderer extends DefaultTreeCellRenderer{ public Component getTreeCellRendererComponent(JTree tree, Object value, boolean selected, boolean expanded, boolean

我正在使用CustomCellRenderer显示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;
    }
}
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() ;
    }
我的要求是在某些外部操作上更改节点的映像。 我正在尝试重新加载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;
    }
}
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() ;
    }

我做错了什么?

将图标作为字段添加到渲染器类中

更改此字段的值并重新绘制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
。当代码调用
gettreecellrendercomponent
时,它必须是一个提供
JComponent
的对象

在您的例子中,将getCellRenderer()转换为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;
        }
    }
}
有两点:

  • 使用类似于
    actionPerformed
    的方法从表中获取渲染器并对其进行修改不是常见做法。应该注意,渲染器是共享的,因此将影响列中使用该渲染器的所有单元格
  • 即使您在执行
    操作期间在渲染器实例上设置了
    图标
    ,渲染器始终通过
    GetTreeCellRenderComponent
    方法访问以进行绘制,并且您始终将图标设置为“white.png”,因此您永远不会显示“black.gif”
  • 您可以选择在
    actionPerformed
    方法中设置模型的状态,然后从
    gettreecellrendercomponent
    中查询要显示的图标

    例如:

    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;    
    }
    

    那么如何解决这个问题呢。请用代码解释。:)是的,它正在更改整个树的图标,而不是所选节点的图标。