Ich versuche eine "unterteilte" Tabelle zu erstellen, die eigentlich mehrere Tabellen innerhalb eines "scrollbaren" JPanel
über GridBagLayout
sind. Die Tabellen teilen sich das gleiche Tabellenmodell (Klasse), Tabellenkopf und Spaltenmodell, die JTableHeader
ist als Spaltenkopfansicht eines JScrollPane
gesetzt, der alles enthält. Es gibt nur eine JScrollPane
.Leere JTables innerhalb eines scrollbaren (GridBagLayout) Panels - Header kollabiert bei Spaltenvergrößerung
frame (BorderLayout)
|- JScrollPane
|- JPanel (GridBagLayout)
|- Section title panel
|- JTable 1
|- Section title panel
|- JTable 2
|- JTable (fake)
|- vertical filler
Alles schien wie erwartet zu arbeiten, bis ich eine beliebige Spalte ohne Werte in eine der beiden Tabellen, um die Größe versucht - wenn die Tabellen mindestens eine Reihe hatte, es funktionierte wie erwartet. Ich überlegte, ob ich "Null" -Reihen in der Tabelle haben sollte, aber das störte das Filtern, Sortieren usw. Also habe ich den Code so geändert, dass er eine "verdeckte" gefälschte Tabelle enthält, die den Header so halten soll, dass er immer eine Zeile hat.
Dies funktioniert jedoch nicht. Sobald eine der Tabellen leer ist und eine Spaltengröße versucht wird, ist der Tabellenkopf beschädigt (eine der Spalten wird verkleinert).
, warum dies geschieht und was kann ich dagegen tun?
import java.awt.BorderLayout;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.LayoutManager;
import java.awt.Rectangle;
import javax.swing.BorderFactory;
import javax.swing.Box;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.Scrollable;
import javax.swing.SwingUtilities;
import javax.swing.UIManager;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.JTableHeader;
import javax.swing.table.TableColumnModel;
import javax.swing.table.TableModel;
public class SectionTables extends JFrame {
public SectionTables() {
setDefaultCloseOperation(EXIT_ON_CLOSE);
setLayout(new BorderLayout());
GridBagConstraints gbc;
JPanel tables = new ScrollableJPanel(new GridBagLayout());
JScrollPane scrollPane = new JScrollPane(tables);
JPanel section1Title = new JPanel(new BorderLayout());
section1Title.setBorder(BorderFactory.createMatteBorder(1, 1, 1, 1, UIManager.getColor("controlShadow")));
JLabel section1 = new JLabel("Section One", null, JLabel.CENTER);
section1Title.add(section1);
gbc = new GridBagConstraints();
gbc.gridx = 0;
gbc.gridy = 0;
gbc.weightx = 1.0d;
gbc.fill = GridBagConstraints.HORIZONTAL;
tables.add(section1Title, gbc);
MyTableModel model1 = new MyTableModel();
JTable table1 = new MyTable(model1);
gbc = new GridBagConstraints();
gbc.gridx = 0;
gbc.gridy = 1;
gbc.weightx = 1.0d;
gbc.fill = GridBagConstraints.HORIZONTAL;
tables.add(table1, gbc);
JPanel section2Title = new JPanel(new BorderLayout());
section2Title.setBorder(BorderFactory.createMatteBorder(1, 1, 1, 1, UIManager.getColor("controlShadow")));
JLabel section2 = new JLabel("Section Two", null, JLabel.CENTER);
section2Title.add(section2);
gbc = new GridBagConstraints();
gbc.gridx = 0;
gbc.gridy = 2;
gbc.weightx = 1.0d;
gbc.fill = GridBagConstraints.HORIZONTAL;
tables.add(section2Title, gbc);
MyTableModel model2 = new MyTableModel();
JTable table2 = new MyTable(model2);
gbc = new GridBagConstraints();
gbc.gridx = 0;
gbc.gridy = 3;
gbc.weightx = 1.0d;
gbc.fill = GridBagConstraints.HORIZONTAL;
tables.add(table2, gbc);
MyTableModel modelFake = new MyTableModel();
modelFake.addRow(new String[] {"", "", ""});
JTable tableFake = new MyObscuredTable();
tableFake.setModel(modelFake);
gbc = new GridBagConstraints();
gbc.gridx = 0;
gbc.gridy = 4;
gbc.weightx = 1.0d;
gbc.fill = GridBagConstraints.HORIZONTAL;
tables.add(tableFake, gbc);
Box.Filler filler1 = new Box.Filler(new Dimension(0, 0), new Dimension(0, 0), new Dimension(0, 32767));
gbc = new GridBagConstraints();
gbc.gridx = 0;
gbc.gridy = 5;
gbc.weighty = 1.0d;
gbc.fill = GridBagConstraints.VERTICAL;
tables.add(filler1, gbc);
add(scrollPane);
TableColumnModel columnModel = table1.getColumnModel();
table2.setColumnModel(columnModel);
tableFake.setColumnModel(columnModel);
JTableHeader tableHeader = new JTableHeader(columnModel);
scrollPane.setColumnHeaderView(tableHeader);
table1.setTableHeader(tableHeader);
table2.setTableHeader(tableHeader);
tableFake.setTableHeader(tableHeader);
// if tables are filled, the issue does not occur
// model1.addRow(new String[] {"", "", ""});
// model2.addRow(new String[] {"", "", ""});
pack();
setLocationRelativeTo(null);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
new SectionTables().setVisible(true);
}
});
}
private class MyTableModel extends DefaultTableModel {
private String[] columnNames = new String[] {"First", "Second", "Third"};
private Class[] columnClasses = new Class[] {String.class, String.class, String.class};
@Override
public int getColumnCount() {
return columnNames.length;
}
@Override
public String getColumnName(int column) {
return columnNames[column];
}
@Override
public Class<?> getColumnClass(int columnIndex) {
return columnClasses[columnIndex];
}
@Override
public boolean isCellEditable(int row, int column) {
return false;
}
}
private class ScrollableJPanel extends JPanel implements Scrollable {
public ScrollableJPanel(LayoutManager layout) {
super(layout);
}
public ScrollableJPanel() {
super();
}
@Override
public Dimension getPreferredScrollableViewportSize() {
return getPreferredSize();
}
@Override
public int getScrollableUnitIncrement(Rectangle visibleRect, int orientation, int direction) {
return 16;
}
@Override
public int getScrollableBlockIncrement(Rectangle visibleRect, int orientation, int direction) {
return 16;
}
@Override
public boolean getScrollableTracksViewportWidth() {
return true;
}
@Override
public boolean getScrollableTracksViewportHeight() {
return false;
}
}
private class MyObscuredTable extends JTable {
@Override
public Dimension getPreferredSize() {
int height;
height = 1; // obscure null row
Container ancestorOfClass = SwingUtilities.getAncestorOfClass(JPanel.class, this);
int width = ancestorOfClass.getWidth();
return new Dimension(width, height);
}
}
private class MyTable extends JTable {
public MyTable(TableModel model) {
super(model);
}
@Override
public Dimension getPreferredSize() {
int height;
height = getRowHeight() * getRowCount();
Container ancestorOfClass = SwingUtilities.getAncestorOfClass(JPanel.class, this);
int width = ancestorOfClass.getWidth();
return new Dimension(width, height);
}
}
}
Funktioniert als ein Charme. Danke, Camickr. Ich poste die endgültige Lösung als separate Antwort und akzeptiere deine. – predi