动态更改 JTree 的节点图像

发布于 2024-08-20 10:04:15 字数 994 浏览 5 评论 0原文

我正在使用 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;
    }
}

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

我哪里做错了??????

I am using a CustomCellRenderer to display nodes of a JTree to display image with a node as
shown below :-

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

My requirement is to change image of the node on some external action.
I am trying to reload the model of JTree, but it's not working as shown below :-

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

Where I am doing wrong??????

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

今天小雨转甜 2024-08-27 10:04:15

有几点:

  1. 通过像 actionPerformed 这样的方法从表中获取渲染器并修改它并不常见。 您也会影响列中使用该渲染器的所有单元格
  2. 您应该注意,渲染器是共享的,因此即使您在 actionPerformed 期间在渲染器实例上设置了 Icon, ,始终通过 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;    
}

a couple points:

  1. grabbing the renderer from the table in a method like actionPerformed and modifying it is not common practice. You should note that the renderer is shared, so you will be affecting all cells in the column that use that renderer
  2. even though you set the Icon on your renderer instance during actionPerformed, the renderer is always accessed for painting via the getTreeCellRendererComponent method, and in that you are always setting the icon to "white.png", so you will never get the "black.gif" to display.

An option you have is to set state on the Model in your actionPerformed method, and then from within the getTreeCellRendererComponent you can query your model for the icon to be displayed.

for example:

public void actionPerformed(ActionEvent ae) {

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

in the renderer:

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;    
}
我一向站在原地 2024-08-27 10:04:15

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

更改此字段的值并重新绘制 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() 转换为 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;
        }
    }
}

Add your Icon to your renderer class as a field.

Change the value of this field and repaint the 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;
    }
}

Edit: explanations

In your case, it is useless to change the model. The icon used to display each of the nodes is a part of the renderer.

The renderer object of the JTree is not forced to be a JComponent. It has to be an object providing a JComponent when the code calls getTreeCellRendererComponent.

In your case, the cast of getCellRenderer() into a JLabel is just plain luck, because the default implementation of the DefaultTreeCellRenderer is an extension of JLabel.

And, in fact, as your renderer did call setIcon on itself, it's normal that your getIcon methods gives you the last icon you did put into the renderer.

Full code working :

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;
        }
    }
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文