TreeTable: Unterschied zwischen den Versionen
Keine Bearbeitungszusammenfassung |
Keine Bearbeitungszusammenfassung |
||
| Zeile 238: | Zeile 238: | ||
public class TreeTable extends JFrame { | public class TreeTable extends JFrame { | ||
private DefaultMutableTreeNode root; | private DefaultMutableTreeNode root; | ||
TreeTablePanel[] treeTablePanels; | |||
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 { | |||
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); | ||
customizeSplitpane(tree, table); | |||
adapter.addTableModelListener(this); | |||
// | // | ||
JScrollPane scrollPane = new JScrollPane(splitPane); | JScrollPane scrollPane = new JScrollPane(splitPane); | ||
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)); | ||
add(header, BorderLayout.NORTH); | |||
btAdd = new JButton(); | btAdd = new JButton(); | ||
| Zeile 299: | Zeile 357: | ||
} | } | ||
}); | }); | ||
} | } | ||
| 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, | tableHeader.setBounds(new Rectangle(loc.x - getLocation().x - 3, 0, 1100, 18)); | ||
} | } | ||
}); | }); | ||
| Zeile 393: | Zeile 426: | ||
} | } | ||
private void | 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 | public void tableChanged(TableModelEvent e) { | ||
for (TreeTablePanel treeTablePanel : treeTablePanels) { | |||
treeTablePanel.getTable().repaint(); | |||
} | |||
} | |||
public Table getTable() { | |||
return table; | |||
} | } | ||
}</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>
