首页 > 解决方案 > 同时使用两个不同的渲染器显示相同的 JTree 实例

问题描述

我正在尝试可视化差异树,它表示两个树结构之间的差异。通常这样的可视化使用一个组件的两个实例来显示左侧和右侧,并向用户指出它们之间的差异,但在我的例子中,差异算法的实际结果是一棵树,其中每个节点最多可能占用两个同时扮演不同的角色(左右角色)。

在用户看来,它必须像两个JTree并排的并排在一起一样。实现如何实现这一点无关紧要。我目前的方法是使用JTree共享模型的两个同步实例。是否有另一种实现方法,可以使用单个JTree实例来实现相同的目标?

两个JTrees,SIDE BY SIDE,是一个要求。

这不是我可以提供可行代码示例的问题类型,但这是一个模拟我的树模型的可切换渲染器:

package org.stackoverflow.example;

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.tree.*;

public class SameTreeNodesRenderedDifferently extends JFrame {
    
    private JTree tree;
    private JButton button;
    private MyTreeCellRenderer leftRenderer;
    private MyTreeCellRenderer rightRenderer;
    private MyTreeCellRenderer currentRenderer;
    
    public SameTreeNodesRenderedDifferently() {
        setDefaultCloseOperation(EXIT_ON_CLOSE);
        setLayout(new BorderLayout()); 
        setTitle("SameTreeNodesRenderedDifferently");
        
        DefaultMutableTreeNode root = new DefaultMutableTreeNode(new MyNode("root"));
        createTree(root);
        tree = new JTree(root);
        JScrollPane scroll = new JScrollPane(tree);
        add(scroll);
        
        leftRenderer = new MyTreeCellRenderer(true);
        rightRenderer = new MyTreeCellRenderer(false);
        currentRenderer = leftRenderer;
        tree.setCellRenderer(currentRenderer);
        expandAll();
        
        button = new JButton("Switch renderer");
        add(button, BorderLayout.PAGE_END);
        button.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent ae) {
                currentRenderer = currentRenderer == leftRenderer ? rightRenderer : leftRenderer;
                tree.setCellRenderer(currentRenderer);
                tree.revalidate();
                tree.repaint();
                expandAll();
            }
        });
        setSize(400, 400);
        setLocationRelativeTo(null);
    }
    
    private void createTree(DefaultMutableTreeNode root) {
        DefaultMutableTreeNode a = new DefaultMutableTreeNode(new MyNode("a"));
        root.add(a);
        DefaultMutableTreeNode b = new DefaultMutableTreeNode(new MyNode("b", "!b"));
        a.add(b);
        DefaultMutableTreeNode c = new DefaultMutableTreeNode(new MyNode("c"));
        a.add(c);
        DefaultMutableTreeNode d = new DefaultMutableTreeNode(new MyNode("d"));
        root.add(d);        
        DefaultMutableTreeNode e = new DefaultMutableTreeNode(new MyNode("e", "!e"));
        d.add(e);       
        DefaultMutableTreeNode f = new DefaultMutableTreeNode(new MyNode("f", "!f"));
        d.add(f);       
        DefaultMutableTreeNode g = new DefaultMutableTreeNode(new MyNode("g", "!g"));
        d.add(g);       
        DefaultMutableTreeNode h = new DefaultMutableTreeNode(new MyNode("h"));
        d.add(h);
    }
    
    private void expandAll() {
        for (int i = 0; i < tree.getRowCount(); i++) {
            tree.expandRow(i);
        }
    }
    
    public static void main(String[] args) {
        SwingUtilities.invokeLater(new Runnable() {
            @Override
            public void run() {
                new SameTreeNodesRenderedDifferently().setVisible(true);
            }
        });
    }
    
    private static class MyTreeCellRenderer extends DefaultTreeCellRenderer {

        private final boolean left;
        
        public MyTreeCellRenderer(boolean left) {
            this.left = left;
        }
        
        @Override
        public Component getTreeCellRendererComponent(JTree tree, Object value, boolean sel, boolean expanded, boolean leaf, int row, boolean hasFocus) {
            super.getTreeCellRendererComponent(tree, value, sel, expanded, leaf, row, hasFocus);
            if (value instanceof DefaultMutableTreeNode) {
                DefaultMutableTreeNode dmtn = (DefaultMutableTreeNode) value;
                MyNode node = (MyNode) dmtn.getUserObject();
                setText(left ? node.leftValue : node.rightValue);
            }
            return this;
        }
        
    }
    
    public static class MyNode {
        private final String leftValue;
        private final String rightValue;
        
        public MyNode(String value) {
            this(value, value);
        }
        
        public MyNode(String leftValue, String rightValue) {
            this.leftValue = leftValue;
            this.rightValue = rightValue;
        }

        public String getLeftValue() {
            return leftValue;
        }

        public String getRightValue() {
            return rightValue;
        }

        @Override
        public String toString() {
            return "MyNode{" + "leftValue=" + leftValue + ", rightValue=" + rightValue + '}';
        }
    }
}

标签: javaswingjtree

解决方案


推荐阅读