Я пытаюсь создать «секционированную» таблицу, которая на самом деле представляет собой несколько таблиц, выложенных в «прокручиваемом» JPanel
через GridBagLayout
. Таблицы используют одну и ту же модель (класс) таблицы, заголовок таблицы и модель столбца, JTableHeader
устанавливается как заголовок заголовка столбца JScrollPane
, который содержит все. Существует только один JScrollPane
.Пустые JTables внутри панели прокручиваемого (GridBagLayout) - заголовок сжимается при изменении размера столбца
frame (BorderLayout)
|- JScrollPane
|- JPanel (GridBagLayout)
|- Section title panel
|- JTable 1
|- Section title panel
|- JTable 2
|- JTable (fake)
|- vertical filler
Все, казалось, работали, как и ожидалось, пока я не попытался изменить размер произвольный столбец без каких-либо значений ни в одной из таблиц - если таблицы, по крайней мере, один ряд, он работал, как ожидалось. Я считал наличие «нулевых» строк в таблице, но это мешает фильтрации, сортировке и т. Д. Таким образом, я изменил код, чтобы содержать «скрытую» поддельную таблицу, которая предназначена для того, чтобы вести заголовок, красиво, всегда имея одну строку.
Это не работает. Как только одна из таблиц пуста и попытка изменить размер столбца, заголовок таблицы поврежден (один из столбцов сжимается).
Почему это происходит и что я могу поделать?
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);
}
}
}
Работает как очарование. Спасибо, камикр. Я отправлю окончательное решение в виде отдельного ответа и приму ваше согласие. – predi