Поместите JTable в JTree - PullRequest
       31

Поместите JTable в JTree

7 голосов
/ 13 января 2012

в связи с потоком Jtable в качестве узла Jtree Я помещаю JTable в JTree, но JTree Представление отображается неправильно при запуске, как я могу setPreferredSize для JTable, потому что PreferredScrollableViewportSize сжимается JTable с рендерингом TableHeader + один Row, один Row остается скрытым, но после расширения узлов TreeRenderer измените и перекрасьте setPreferredSize в ожидаемый Dimension

enter image description here enter image description here

import java.awt.*;
import javax.swing.*;
import javax.swing.table.DefaultTableModel;
import javax.swing.tree.*;

public class TreeWithTableRenderer extends JFrame {

    private static final long serialVersionUID = 1L;
    private JTree tree;

    public TreeWithTableRenderer() {
        DefaultMutableTreeNode AA1 = new DefaultMutableTreeNode("AA1");
        DefaultMutableTreeNode AA2 = new DefaultMutableTreeNode("AA2");
        DefaultMutableTreeNode A = new DefaultMutableTreeNode("A");
        A.add(AA1);
        A.add(AA2);
        DefaultMutableTreeNode BB1 = new DefaultMutableTreeNode("BB1");
        DefaultMutableTreeNode BB2 = new DefaultMutableTreeNode("BB2");
        DefaultMutableTreeNode B = new DefaultMutableTreeNode("B");
        B.add(BB1);
        B.add(BB2);
        DefaultMutableTreeNode CC1 = new DefaultMutableTreeNode("CC1");
        DefaultMutableTreeNode CC2 = new DefaultMutableTreeNode("CC2");
        DefaultMutableTreeNode C = new DefaultMutableTreeNode("C");
        C.add(CC1);
        C.add(CC2);
        DefaultMutableTreeNode root = new DefaultMutableTreeNode("root");
        root.add(A);
        root.add(B);
        root.add(C);
        tree = new JTree(root);
        tree.setCellRenderer(new MyTableInTreeCellRenderer());
        tree.setRowHeight(0);
        JScrollPane jsp = new JScrollPane(tree);
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        add(jsp, BorderLayout.CENTER);
        pack();
        setLocationRelativeTo(null);
    }

    class MyTableInTreeCellRenderer extends JPanel implements TreeCellRenderer {

        private static final long serialVersionUID = 1L;
        private JTable table;

        public MyTableInTreeCellRenderer() {
            super(new BorderLayout());
            table = new JTable();
            JScrollPane scrollPane = new JScrollPane(table);
            add(scrollPane);
        }

        public Component getTreeCellRendererComponent(JTree tree, Object value,
                boolean selected, boolean expanded, boolean leaf, int row, boolean hasFocus) {
            final String v = (String) ((DefaultMutableTreeNode) value).getUserObject();
            table.setModel(new DefaultTableModel() {

                private static final long serialVersionUID = 1L;

                @Override
                public int getRowCount() {
                    return 2;
                }

                @Override
                public int getColumnCount() {
                    return 2;
                }

                @Override
                public Object getValueAt(int row, int column) {
                    return v + ":" + row + ":" + column;
                }
            });
            table.setPreferredScrollableViewportSize(table.getPreferredSize());
            return this;
        }
    }

    public static void main(String[] args) throws Exception {
        SwingUtilities.invokeLater(new Runnable() {

            public void run() {
                new TreeWithTableRenderer().setVisible(true);
            }
        });
    }
}

Ответы [ 2 ]

4 голосов
/ 13 января 2012

Избавьтесь от scrollPane, он все равно не работает (пока я согласен с Расселом :-) и добавьте таблицу и ее заголовок на панель, используя соответствующий LayoutManager:

public MyTableInTreeCellRenderer() {
    super();
    setLayout(new BoxLayout(this, BoxLayout.PAGE_AXIS));
    table = new JTable();
    add(table.getTableHeader());
    add(table);
}

вероятно, нужно немного подправить визуальные эффекты, отсутствуют линии левой и верхней границ - не совсем уверен, какой компонент их обычно рисует, может быть scrollPane

Edit

Забыл: причина запроса prefSize scrollPane при расчете необходимого размера (выполненного в делегате пользовательского интерфейса, а именно VariableHeightLayoutCache) компонента рендеринга заключается в том, что scrollPane еще не настроен с заголовком.Запрос выполняется до того, как панель добавляется в rendererPane, полная настройка выполняется в таблице addNotify, которая происходит только после добавления панели в иерархию

3 голосов
/ 13 января 2012

Вы можете просто избавиться от ScrollPane и расположить заголовок и таблицу непосредственно на панели (с помощью null LayoutManager, чтобы вы могли контролировать все самостоятельно):

static class TableTreeCellRenderer extends JPanel implements TreeCellRenderer {
    private final JTable table;

    TableTreeCellRenderer() {
        table = new JTable();
        setLayout(null);
        add(table.getTableHeader());
        add(table);
    }

    public Dimension getPreferredSize() {
        Dimension headerSize = table.getTableHeader().getPreferredSize();
        Dimension tableSize = table.getPreferredSize();

        return new Dimension(Math.max(headerSize.width, tableSize.width),
                headerSize.height + tableSize.height);
    }

    public void setBounds(int x, int y, int width, int height) {
        super.setBounds(x, y, width, height);
        int headerHeight = table.getTableHeader().getPreferredSize().height;
        table.getTableHeader().setBounds(0, 0, width, headerHeight);
        table.setBounds(0, headerHeight, width, height - headerHeight);
    }

    public Component getTreeCellRendererComponent(JTree tree, Object value,
            boolean selected, boolean expanded, boolean leaf, int row, boolean hasFocus) {
        final String v = (String) ((DefaultMutableTreeNode) value).getUserObject();
        table.setModel(new DefaultTableModel(new Object[][] { 
                { v + "0", "1" },
                { v + "2", "3" }
        }, new Object[] { "id", "value" } ));
        invalidate();
        return this;
    }
}
...