TreeTable: Unterschied zwischen den Versionen

Aus Byte-Welt Wiki
Zur Navigation springenZur Suche springen
Zeile 238: Zeile 238:
 
public class TreeTable extends JFrame {
 
public class TreeTable extends JFrame {
  
    private JTableHeader tableHeader;
 
    private JTree tree;
 
    private TableAdapter adapter;
 
    private Table table;
 
    private JButton btAdd;
 
 
     private DefaultMutableTreeNode root;
 
     private DefaultMutableTreeNode root;
     private JSplitPane splitPane;
+
     TreeTablePanel[] treeTablePanels;
    private Color selectionColor;
 
    private Rectangle selectedRowBounds;
 
  
 
     public TreeTable() {
 
     public TreeTable() {
 
         super("Tree Table Demo");
 
         super("Tree Table Demo");
 
         setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
 
         setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
 +
        DefaultTreeModel model = new DefaultTreeModel(createTree());
 +
        setLayout(new GridLayout(0, 1));
 +
        treeTablePanels = new TreeTablePanel[3];
 +
        for (int i = 0; i < treeTablePanels.length; i++) {
 +
            treeTablePanels[i] = new TreeTablePanel(model, treeTablePanels);
 +
            add(treeTablePanels[i]);
 +
        }
 +
 +
        pack();
 +
    }
 +
 +
    private DefaultMutableTreeNode createTree() {
 +
        // create root node and add more nodes
 +
        root = new DefaultMutableTreeNode(new TableNode("World", new Integer(10), Color.YELLOW));
 +
 +
        DefaultMutableTreeNode n = new DefaultMutableTreeNode(new TableNode("Europe", new Integer(5), Color.GREEN));
 +
        root.add(n);
 +
 +
        DefaultMutableTreeNode n1 = new DefaultMutableTreeNode(new TableNode("Finland", new Integer(1), Color.ORANGE));
 +
        n.add(n1);
 +
 +
        n1 = new DefaultMutableTreeNode(new TableNode("Romania", new Integer(1), Color.RED));
 +
        n.add(n1);
 +
 +
        n1 = new DefaultMutableTreeNode(new TableNode("Germany", new Integer(3), Color.BLUE));
 +
        n.add(n1);
 +
 +
        n = new DefaultMutableTreeNode(new TableNode("America", new Integer(4), Color.WHITE));
 +
        root.add(n);
 +
 +
        n = new DefaultMutableTreeNode(new TableNode("Asia", new Integer(1), Color.MAGENTA));
 +
        root.add(n);
 +
 +
        return root;
 +
    }
 +
 +
    public static void main(final String[] args) {
 +
        Runnable gui = new Runnable() {
 +
 +
            @Override
 +
            public void run() {
 +
                try {
 +
                    UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
 +
                } catch (Exception ex) {
 +
                    ex.printStackTrace();
 +
                }
 +
                new TreeTable().setVisible(true);
 +
            }
 +
        };
 +
        //GUI must start on EventDispatchThread:
 +
        SwingUtilities.invokeLater(gui);
 +
    }
 +
}
 +
 +
class TreeTablePanel extends JPanel implements TableModelListener {
  
        tree = new JTree(createTree()) {
+
    private JTree tree;
 +
    private Rectangle selectedRowBounds;
 +
    private Color selectionColor;
 +
    private TableAdapter adapter;
 +
    private Table table;
 +
    private JSplitPane splitPane;
 +
    private JTableHeader tableHeader;
 +
    private JButton btAdd;
 +
    private TreeTablePanel[] treeTablePanels;
  
 +
    public TreeTablePanel(DefaultTreeModel model, TreeTablePanel[] treeTablePanels) {
 +
        super(new BorderLayout());
 +
        this.treeTablePanels = treeTablePanels;
 +
        tree = new JTree(model) {
 
             //Override paintComponent of JTree:
 
             //Override paintComponent of JTree:
 +
 
             @Override
 
             @Override
 
             public void paintComponent(final Graphics g) {
 
             public void paintComponent(final Graphics g) {
Zeile 270: Zeile 331:
 
         customizeTable(table);
 
         customizeTable(table);
 
         customizeTree(tree, table);
 
         customizeTree(tree, table);
         customizeSplipane(tree, table);
+
         customizeSplitpane(tree, table);
 +
        adapter.addTableModelListener(this);
 
         //
 
         //
 
 
         JScrollPane scrollPane = new JScrollPane(splitPane);
 
         JScrollPane scrollPane = new JScrollPane(splitPane);
         getContentPane().add(scrollPane, BorderLayout.CENTER);
+
         add(scrollPane, BorderLayout.CENTER);
 
         JPanel header = new JPanel(null);
 
         JPanel header = new JPanel(null);
 
         tableHeader = table.getTableHeader();
 
         tableHeader = table.getTableHeader();
 
         header.add(tableHeader);
 
         header.add(tableHeader);
 
         header.setPreferredSize(new Dimension(0, 16));
 
         header.setPreferredSize(new Dimension(0, 16));
         getContentPane().add(header, BorderLayout.NORTH);
+
         add(header, BorderLayout.NORTH);
 
 
        setSize(400, 300);
 
        setLocationRelativeTo(null);
 
  
 
         btAdd = new JButton();
 
         btAdd = new JButton();
Zeile 299: Zeile 357:
 
             }
 
             }
 
         });
 
         });
    }
 
 
    private DefaultMutableTreeNode createTree() {
 
        // create root node and add more nodes
 
        root = new DefaultMutableTreeNode(new TableNode("World", new Integer(10), Color.YELLOW));
 
 
        DefaultMutableTreeNode n = new DefaultMutableTreeNode(new TableNode("Europe", new Integer(5), Color.GREEN));
 
        root.add(n);
 
 
        DefaultMutableTreeNode n1 = new DefaultMutableTreeNode(new TableNode("Finland", new Integer(1), Color.ORANGE));
 
        n.add(n1);
 
 
        n1 = new DefaultMutableTreeNode(new TableNode("Romania", new Integer(1), Color.RED));
 
        n.add(n1);
 
 
        n1 = new DefaultMutableTreeNode(new TableNode("Germany", new Integer(3), Color.BLUE));
 
        n.add(n1);
 
 
        n = new DefaultMutableTreeNode(new TableNode("America", new Integer(4), Color.WHITE));
 
        root.add(n);
 
 
        n = new DefaultMutableTreeNode(new TableNode("Asia", new Integer(1), Color.MAGENTA));
 
        root.add(n);
 
 
        return root;
 
 
     }
 
     }
  
Zeile 336: Zeile 369:
 
             public void componentResized(ComponentEvent e) {
 
             public void componentResized(ComponentEvent e) {
 
                 Point loc = table.getLocationOnScreen();
 
                 Point loc = table.getLocationOnScreen();
                 tableHeader.setBounds(new Rectangle(loc.x - getLocation().x - 3, 0, 3000, 18));
+
                 tableHeader.setBounds(new Rectangle(loc.x - getLocation().x - 3, 0, 1100, 18));
 
             }
 
             }
 
         });
 
         });
Zeile 393: Zeile 426:
 
     }
 
     }
  
     private void customizeSplipane(final JTree tree, final JTable table) {
+
     private void customizeSplitpane(final JTree tree, final JTable table) {
 
         splitPane = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, tree, table);
 
         splitPane = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, tree, table);
 
         splitPane.setDividerLocation(150);
 
         splitPane.setDividerLocation(150);
Zeile 399: Zeile 432:
 
         splitPane.setContinuousLayout(true);
 
         splitPane.setContinuousLayout(true);
 
     }
 
     }
 
 
     //This method is called in valueChanged, treeCollapsed and treeExpanded
 
     //This method is called in valueChanged, treeCollapsed and treeExpanded
 
     //to paint the selection rectangle:
 
     //to paint the selection rectangle:
 +
 
     private void paintSelectionRect() {
 
     private void paintSelectionRect() {
 
         //Get selected row bounds:
 
         //Get selected row bounds:
Zeile 414: Zeile 447:
 
     }
 
     }
  
     public static void main(final String[] args) {
+
     public void tableChanged(TableModelEvent e) {
         Runnable gui = new Runnable() {
+
         for (TreeTablePanel treeTablePanel : treeTablePanels) {
 +
            treeTablePanel.getTable().repaint();
 +
        }
 +
    }
  
            @Override
+
    public Table getTable() {
            public void run() {
+
         return table;
                try {
 
                    UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
 
                } catch (Exception ex) {
 
                    ex.printStackTrace();
 
                }
 
                new TreeTable().setVisible(true);
 
            }
 
        };
 
         //GUI must start on EventDispatchThread:
 
        SwingUtilities.invokeLater(gui);
 
 
     }
 
     }
 
}</code=java>
 
}</code=java>

Version vom 25. Februar 2009, 15:57 Uhr

Hier ist eine einfache Implementation einer TreeTable (gem. Alexandru Toth), die ein gemeinsames Model für JTree und JTable benutzt. Es ist dann kein Problem mehr, dynamisch neue Zeilen hinzuzufügen:

<code=java>package treetable;

import java.awt.Color; import javax.swing.*; import javax.swing.table.*;

/** JTable that has different renderers depending on the classes in TreeModel */ public class Table extends JTable {

   void registerRenderers() {
       setDefaultRenderer(Color.class, new TableColorRenderer(Color.WHITE));
   }
   public Table() {
       super();
       registerRenderers();
   }
   public Table(TableModel dm) {
       super(dm);
       registerRenderers();
   }
   public Table(TableModel dm, TableColumnModel cm) {
       super(dm, cm);
       registerRenderers();
   }
   @Override
   public TableCellRenderer getCellRenderer(int row, int column) {
       Object value = getModel().getValueAt(row, column);
       /** enable to have custom renderers depending on class of cell */
       TableCellRenderer tcr = getDefaultRenderer(value.getClass());
       return tcr;
   }

}</code=java>

<code=java>package treetable;

import javax.swing.*; import javax.swing.event.*; import javax.swing.tree.*; import javax.swing.table.*; import java.util.Vector;

public class TableAdapter extends AbstractTableModel {

   private JTree tree;
   private JTable table;
   private int[] sel_rows;
   private ListSelectionListener selectionListener;
   public TableAdapter(JTree t) {
       tree = t;
       tree.addTreeExpansionListener(new TreeExpansionListener() {
           public void treeExpanded(TreeExpansionEvent event) {
               fireTableDataChanged();
               select();
           }
           public void treeCollapsed(TreeExpansionEvent event) {
               fireTableDataChanged();
               select();
           }
       });
   }
   public void addTable(JTable t) {
       table = t;
       tree.addTreeSelectionListener(new TreeSelectionListener() {
           public void valueChanged(TreeSelectionEvent e) {
               sel_rows = tree.getSelectionRows();
               select();
           }
       });
       selectionListener = new ListSelectionListener() {
           public void valueChanged(ListSelectionEvent e) {
               int row = table.getSelectedRow();
               tree.setSelectionRow(row);
           }
       };
       table.getSelectionModel().addListSelectionListener(selectionListener);
   }
   private void select() {
       if (sel_rows != null) {
           table.getSelectionModel().setSelectionInterval(sel_rows[0], sel_rows[0]);
       }
   }
   //assumes all nodes have same number of items as root node
   public int getColumnCount() {
       DefaultMutableTreeNode root = (DefaultMutableTreeNode) tree.getModel().getRoot();
       TableNode n = (TableNode) root.getUserObject();
       return n.getDataRow().size();
   }
   public int getRowCount() {
       return tree.getRowCount();
   }
   @Override
   public String getColumnName(int col) {
       return new String("col" + col);
   }
   public Object getValueAt(int row, int col) {
       TreePath tPath = tree.getPathForRow(row);
       Object[] oPath = tPath.getPath();
       int len = oPath.length;
       DefaultMutableTreeNode node = (DefaultMutableTreeNode) oPath[len - 1];
       TableNode treeNode = (TableNode) node.getUserObject();
       Vector dataRow = treeNode.getDataRow();
       return dataRow.elementAt(col);
   }
   @Override
   public void setValueAt(Object value, int row, int col) {
       TreePath tPath = tree.getPathForRow(row);
       Object[] oPath = tPath.getPath();
       int len = oPath.length;
       DefaultMutableTreeNode node = (DefaultMutableTreeNode) oPath[len - 1];
       TableNode treeNode = (TableNode) node.getUserObject();
       Vector dataRow = treeNode.getDataRow();
       dataRow.setElementAt(value, col);
   }
   @Override
   public Class getColumnClass(int c) {
       DefaultMutableTreeNode root = (DefaultMutableTreeNode) tree.getModel().getRoot();
       TableNode n = (TableNode) root.getUserObject();
       return n.getDataRow().elementAt(c).getClass();
   }
   @Override
   public boolean isCellEditable(int rowIndex, int columnIndex) {
       return true;
   }

}</code=java>

<code=java>package treetable;

import java.awt.*; import javax.swing.*; import javax.swing.table.*; import javax.swing.border.*;

public class TableColorRenderer extends JLabel implements TableCellRenderer {

   Border unselectedBorder = null;
   Border selectedBorder = null;
   boolean isBordered = true;
   public TableColorRenderer(Color color) {
       super();
       setOpaque(true);
       setBackground(color);
   }
   public Component getTableCellRendererComponent(
           JTable table, Object value,
           boolean isSelected, boolean hasFocus,
           int row, int column) {
       if (isSelected) {
           if (selectedBorder == null) {
               selectedBorder = BorderFactory.createMatteBorder(2, 5, 2, 5,
                       table.getSelectionBackground());
           }
           setBorder(selectedBorder);
       } else {
           if (unselectedBorder == null) {
               unselectedBorder = BorderFactory.createMatteBorder(2, 5, 2, 5,
                       table.getBackground());
           }
           setBorder(unselectedBorder);
       }
       if (value.getClass() == Color.class) {
           setBackground((Color) value);
       } else {
           setBackground(Color.WHITE);
       }
       return this;
   }

}</code=java>

<code=java>package treetable;

import java.util.*;

public class TableNode {

   private String label;
   private Vector dataRow;
   public TableNode(String s, Object x, Object y) {
       label = s;
       dataRow = new Vector();
       dataRow.add(x);
       dataRow.add(y);
   }
   @Override
   public String toString() {
       return label;
   }
   public Vector getDataRow() {
       return dataRow;
   }

}</code=java>

<code=java>package treetable;

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

public class TreeTable extends JFrame {

   private DefaultMutableTreeNode root;
   TreeTablePanel[] treeTablePanels;
   public TreeTable() {
       super("Tree Table Demo");
       setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
       DefaultTreeModel model = new DefaultTreeModel(createTree());
       setLayout(new GridLayout(0, 1));
       treeTablePanels = new TreeTablePanel[3];
       for (int i = 0; i < treeTablePanels.length; i++) {
           treeTablePanels[i] = new TreeTablePanel(model, treeTablePanels);
           add(treeTablePanels[i]);
       }
       pack();
   }
   private DefaultMutableTreeNode createTree() {
       // create root node and add more nodes
       root = new DefaultMutableTreeNode(new TableNode("World", new Integer(10), Color.YELLOW));
       DefaultMutableTreeNode n = new DefaultMutableTreeNode(new TableNode("Europe", new Integer(5), Color.GREEN));
       root.add(n);
       DefaultMutableTreeNode n1 = new DefaultMutableTreeNode(new TableNode("Finland", new Integer(1), Color.ORANGE));
       n.add(n1);
       n1 = new DefaultMutableTreeNode(new TableNode("Romania", new Integer(1), Color.RED));
       n.add(n1);
       n1 = new DefaultMutableTreeNode(new TableNode("Germany", new Integer(3), Color.BLUE));
       n.add(n1);
       n = new DefaultMutableTreeNode(new TableNode("America", new Integer(4), Color.WHITE));
       root.add(n);
       n = new DefaultMutableTreeNode(new TableNode("Asia", new Integer(1), Color.MAGENTA));
       root.add(n);
       return root;
   }
   public static void main(final String[] args) {
       Runnable gui = new Runnable() {
           @Override
           public void run() {
               try {
                   UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
               } catch (Exception ex) {
                   ex.printStackTrace();
               }
               new TreeTable().setVisible(true);
           }
       };
       //GUI must start on EventDispatchThread:
       SwingUtilities.invokeLater(gui);
   }

}

class TreeTablePanel extends JPanel implements TableModelListener {

   private JTree tree;
   private Rectangle selectedRowBounds;
   private Color selectionColor;
   private TableAdapter adapter;
   private Table table;
   private JSplitPane splitPane;
   private JTableHeader tableHeader;
   private JButton btAdd;
   private TreeTablePanel[] treeTablePanels;
   public TreeTablePanel(DefaultTreeModel model, TreeTablePanel[] treeTablePanels) {
       super(new BorderLayout());
       this.treeTablePanels = treeTablePanels;
       tree = new JTree(model) {
           //Override paintComponent of JTree:
           @Override
           public void paintComponent(final Graphics g) {
               if (selectedRowBounds != null) {
                   //Set selection Color:
                   g.setColor(selectionColor);
                   //Draw selection rectangle using the width of JTree:
                   g.fillRect(0, (int) selectedRowBounds.getY(), getWidth(), (int) selectedRowBounds.getHeight());
               }
               super.paintComponent(g);
           }
       };
       adapter = new TableAdapter(tree);
       table = new Table(adapter);
       customizeTable(table);
       customizeTree(tree, table);
       customizeSplitpane(tree, table);
       adapter.addTableModelListener(this);
       //
       JScrollPane scrollPane = new JScrollPane(splitPane);
       add(scrollPane, BorderLayout.CENTER);
       JPanel header = new JPanel(null);
       tableHeader = table.getTableHeader();
       header.add(tableHeader);
       header.setPreferredSize(new Dimension(0, 16));
       add(header, BorderLayout.NORTH);
       btAdd = new JButton();
       add(btAdd, BorderLayout.SOUTH);
       btAdd.setAction(new AbstractAction("Add") {
           public void actionPerformed(ActionEvent e) {
               DefaultMutableTreeNode n = new DefaultMutableTreeNode(new TableNode("NEW", new Integer(5), Color.GREEN));
               DefaultMutableTreeNode parent = (DefaultMutableTreeNode) tree.getLastSelectedPathComponent();
               if (parent != null) {
                   parent.add(n);
                   ((DefaultTreeModel) tree.getModel()).nodeStructureChanged(parent);
                   table.repaint();
                   validate();
               }
           }
       });
   }
   private void customizeTable(final JTable table) {
       table.getSelectionModel().setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
       //connect Selection listeners
       adapter.addTable(table);
       table.setRowHeight(18);
       table.addComponentListener(new ComponentAdapter() {
           @Override
           public void componentResized(ComponentEvent e) {
               Point loc = table.getLocationOnScreen();
               tableHeader.setBounds(new Rectangle(loc.x - getLocation().x - 3, 0, 1100, 18));
           }
       });
   }
   private void customizeTree(final JTree tree, final JTable table) {
       tree.setRowHeight(table.getRowHeight());
       tree.setFocusable(false);
       selectionColor = table.getSelectionBackground();
       tree.putClientProperty("JTree.lineStyle", "Horizontal");
       tree.getSelectionModel().setSelectionMode(TreeSelectionModel.SINGLE_TREE_SELECTION);
       tree.setOpaque(false);
       //Adapt the default selection colors:
       DefaultTreeCellRenderer renderer = (DefaultTreeCellRenderer) tree.getCellRenderer();
       renderer.setBorderSelectionColor(Color.WHITE);
       renderer.setBackgroundSelectionColor(new Color(0, 0, 0, 0));
       //Add the TreeSelectionListener:
       TreeSelectionModel selectionModel = tree.getSelectionModel();
       selectionModel.addTreeSelectionListener(new TreeSelectionListener() {
           public void valueChanged(final TreeSelectionEvent e) {
               paintSelectionRect();
           }
       });
       //Add the TreeExpansionListener:
       tree.addTreeExpansionListener(new TreeExpansionListener() {
           public void treeCollapsed(final TreeExpansionEvent event) {
               paintSelectionRect();
           }
           public void treeExpanded(final TreeExpansionEvent event) {
               paintSelectionRect();
           }
       });
       //Add MouseListener if you want to listen to whole line width:
       tree.addMouseListener(new MouseAdapter() {
           @Override
           public void mousePressed(final MouseEvent e) {
               int row = tree.getClosestRowForLocation(e.getX(), e.getY());
               if (e.getClickCount() == 2) {
                   if (tree.isCollapsed(row)) {
                       tree.expandRow(row);
                   } else {
                       tree.collapseRow(row);
                   }
               } else {
                   tree.setSelectionRow(row);
               }
           }
       });
   }
   private void customizeSplitpane(final JTree tree, final JTable table) {
       splitPane = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, tree, table);
       splitPane.setDividerLocation(150);
       splitPane.setBackground(Color.WHITE);
       splitPane.setContinuousLayout(true);
   }
   //This method is called in valueChanged, treeCollapsed and treeExpanded
   //to paint the selection rectangle:
   private void paintSelectionRect() {
       //Get selected row bounds:
       int[] rows = tree.getSelectionRows();
       if (rows == null) {
           selectedRowBounds = null;
           return;
       }
       selectedRowBounds = tree.getRowBounds(rows[0]);
       //Repaint the JTree:
       tree.repaint();
   }
   public void tableChanged(TableModelEvent e) {
       for (TreeTablePanel treeTablePanel : treeTablePanels) {
           treeTablePanel.getTable().repaint();
       }
   }
   public Table getTable() {
       return table;
   }

}</code=java>