Showing a JTable in a JTree behaves differently with different look and feels

泪湿孤枕 提交于 2019-12-25 01:08:29

问题


I have a JTree where some of the data to be shown should be shown in a JTable. So to do this, I created a renderer class (extending DefaultTreeCellRenderder) to change the rendered component returned depending on what the object value contains when initially passed into the renderer.

If it is a table to be shown, it is contained within a JScrollPane (as the below code shows).

This works (in that the JScrollPane containing the JTable is shown in its entirety) with the Cross Platform Look and Feel but when using the System Look and Feel, the JScrollPane seems to be constrained to the height of the leaf node. Is there a way of changing this so it acts like the Cross Platform look and feel?

JFrame

public class ExampleJTreeWithJTable extends JFrame {

    public ExampleJTreeWithJTable() {
        setLayout(new BorderLayout(0, 0));
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        DefaultMutableTreeNode root = new DefaultMutableTreeNode("Example");
        root.add(new DefaultMutableTreeNode("TABLE:Column A=Cell 1.1,Cell 2.1,Cell 3.1¬Column B=Cell 1.2,Cell 2.2,Cell 3.2"));

        JTree tree = new JTree(root);
        tree.setCellRenderer(new ExampleRenderer());

        add(tree, BorderLayout.CENTER);
        pack();
    }

    public static void main(String... args) {
        try {
            UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); // Using getCrossPlatformLookAndFeelClassName works...

            EventQueue.invokeLater(new Runnable() {

                @Override
                public void run() {
                    ExampleJTreeWithJTable window = new ExampleJTreeWithJTable();
                    window.setLocationRelativeTo(null);
                    window.setVisible(true);
                }
            });
        } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException e) {
            e.printStackTrace();
        }
    }
}

Renderer

public class ExampleRenderer extends DefaultTreeCellRenderer {
    private Map<String, JScrollPane> tables = new HashMap<String, JScrollPane>();

    @Override
    public Component getTreeCellRendererComponent(JTree tree, Object value, boolean sel, boolean expanded, boolean leaf, int row, boolean hasFocus) {
        Component c = super.getTreeCellRendererComponent(tree, value, sel, expanded, leaf, row, hasFocus);

        if (value.toString().startsWith("TABLE:")) {
            c = tables.get(value.toString());

            if (c == null) {
                JTable table = new JTable(createModel(value.toString()));
                table.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);

                JScrollPane pane = new JScrollPane(table);

                tables.put(value.toString(), pane);
                c = tables.get(value.toString());
            }
        }

        return c;
    }

    private TableModel createModel(String tableData) {
        tableData = tableData.substring(6, tableData.length());

        DefaultTableModel model = new DefaultTableModel();
        String[] colData = tableData.split("¬");

        for (String data : colData) {
            String[] components = data.split("=");
            model.addColumn(components[0], components[1].split(","));
        }

        return model;
    }
}

Examples of output

Cross Platform Look and Feel

System Look and Feel

I've tried manually setting the JScrollPane to the preferred size of the JTable with no effect. I have a feeling it is to do with how the System LAF calculates the height of the component against the leaf node but I am not certain here.

I have also tried simply showing the JTable rather than the JScrollPane. In the Cross Platform LAF, this works. In the System LAF, it shows the first row of the table.


回答1:


I figured this out from the below link:

https://www.daniweb.com/software-development/java/threads/386037/different-height-of-jtree-nodes

In essence, all that is needed to do is set the row height to 0 to make the leaf node height variable, depending on the component being rendered as opposed to a fixed (I presume) default value.

Therefore, the code would look like this:

JTree tree = new JTree(root);
tree.setRowHeight(0);
tree.setCellRenderer(new ExampleRenderer());

The result is this:



来源:https://stackoverflow.com/questions/28675009/showing-a-jtable-in-a-jtree-behaves-differently-with-different-look-and-feels

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!