У меня есть элемент Swing UI, который использует вложенные JTables.То есть TableCellRenderer внешней таблицы возвращает объекты JTable в качестве компонента для визуализации для каждой ячейки.Этот код прекрасно работает в Java 8. Использование точно такого же кода в Java 9 или Java 10 приводит к тому, что внутренняя таблица не перерисовывается должным образом при прокрутке таблицы.При изменении размера окна таблица перерисовывается должным образом.
Редактировать: я еще немного покопался и отследил проблему до строк 1862: 1877 в BasicTableUI.java - эти строки были добавлены в Java 9. Если я сделаю свойСобственный TableUI без этих строк проблема исчезает.Из отладки выясняется, что проблема в том, что в моем случае rMin и rMax равны, а установка rMax = rMax - 1 делает rMax
См. SSCE ниже:
package testing.test_painting;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.plaf.basic.BasicTableHeaderUI;
import javax.swing.table.AbstractTableModel;
import javax.swing.table.JTableHeader;
import javax.swing.table.TableCellRenderer;
import javax.swing.table.TableColumn;
import javax.swing.table.TableColumnModel;
import javax.swing.table.TableModel;
import java.awt.Component;
import java.awt.Dimension;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
class InnerTable extends JTable {
public InnerTable(TableModel dm) {
super(dm);
}
}
class InnerTableModel extends AbstractTableModel {
@Override
public int getRowCount() {
return 500;
}
@Override
public int getColumnCount() {
return 10;
}
@Override
public Object getValueAt(int rowIndex, int columnIndex) {
return rowIndex + "," + columnIndex;
}
}
class OuterTableModel extends AbstractTableModel {
private final List<JTable> termTables;
public OuterTableModel() {
this.termTables = Arrays.asList(new InnerTable(new InnerTableModel()));
}
@Override
public int getRowCount() {
return 1;
}
@Override
public int getColumnCount() {
return termTables.size();
}
@Override
public Object getValueAt(int rowIndex, int columnIndex) {
return termTables.get(columnIndex);
}
public JTable getTermTable(int modelColumn) {
return termTables.get(modelColumn);
}
}
class OuterTable extends JTable {
private final List<TableRenderer> renderers;
private class TableRenderer implements TableCellRenderer {
private final OuterTableModel tableModel;
public TableRenderer(OuterTableModel tableModel) {
this.tableModel = tableModel;
}
@Override
public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
int modelColumn = convertColumnIndexToModel(column);
JTable termTable = tableModel.getTermTable(modelColumn);
termTable.setVisible(true);
return termTable;
}
}
private final OuterTableModel tableModel;
public OuterTable(OuterTableModel tableModel) {
super(tableModel);
renderers = new ArrayList<>(tableModel.getColumnCount());
for (int i = 0; i < tableModel.getColumnCount(); i++) {
renderers.add(new TableRenderer(tableModel));
}
this.tableModel = tableModel;
setCellDimensions();
}
@Override
public void setTableHeader(JTableHeader tableHeader) {
tableHeader.setUI(new BasicTableHeaderUI());
super.setTableHeader(tableHeader);
}
private void setCellDimensions() {
Dimension preferredSize = tableModel.getTermTable(0).getPreferredSize();
if (getRowHeight() != preferredSize.height) {
setRowHeight(preferredSize.height);
}
TableColumnModel columnModel = getColumnModel();
for (int i = 0; i < columnModel.getColumnCount(); i++) {
TableColumn column = columnModel.getColumn(i);
column.setMinWidth(preferredSize.width);
column.setMaxWidth(preferredSize.width);
column.setPreferredWidth(preferredSize.width);
column.setWidth(preferredSize.width);
}
setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
}
@Override
public TableCellRenderer getCellRenderer(int row, int column) {
return renderers.get(column);
}
}
public class TestNestedTable {
public static void main(String[] args) {
OuterTableModel mainTableModel = new OuterTableModel();
OuterTable mainTable = new OuterTable(mainTableModel);
JFrame jFrame = new JFrame();
JScrollPane scrollPane = new JScrollPane(mainTable);
scrollPane.getVerticalScrollBar().setUnitIncrement(10);
jFrame.getContentPane().add(scrollPane);
jFrame.pack();
jFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
jFrame.setVisible(true);
}
}