Проблема перекрашивания при прокрутке вложенной таблицы в Java 9+ - PullRequest
0 голосов
/ 05 февраля 2019

У меня есть элемент 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);
    }
}

1 Ответ

0 голосов
/ 06 февраля 2019

сделать свой собственный TableUI без этих строк, проблема исчезает.

Или, проще, вы можете использовать JViewport # SIMPLE_SCROLL_MODE :

JScrollPane scrollPane = new JScrollPane(mainTable);
scrollPane.getVerticalScrollBar().setUnitIncrement(10);
scrollPane.getViewport().setScrollMode(JViewport.SIMPLE_SCROLL_MODE);
...