Очень необычная подсветка ячеек в JXTable

У меня есть JXTable, настроенный для рисования выбранной ячейки в определенный цвет. Однако всякий раз, когда выбранная ячейка находится в верхней строке, создается впечатление, что ВСЕ ячейки таблицы окрашены.

Может кто-нибудь помочь мне понять, почему и как решить эту проблему?

Самый маленький рабочий пример, демонстрирующий эту проблему, приведен ниже.

Дополнительная информация: DefaultTableCellRenderer повторно применяется каждый раз, когда вызывается Paint(), потому что это заполнитель для CustomTableCellRenderer, который я использую в своей полной программе. Интересно, что если я удалю строку DefaultTableCellRenderer, моя проблема будет решена. Почему это? Конечно, если рендерер не указан, то по умолчанию используется в любом случае??

import java.awt.Color;
import java.awt.Component;
import java.util.ArrayList;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
import javax.swing.table.AbstractTableModel;
import javax.swing.table.DefaultTableCellRenderer;
import org.jdesktop.swingx.JXTable;
import org.jdesktop.swingx.decorator.ColorHighlighter;
import org.jdesktop.swingx.decorator.ComponentAdapter;
import org.jdesktop.swingx.decorator.HighlightPredicate;

public class MainClass {
    public static void main(String[] args) {
        JFrame frame = new JFrame();
        CustomTableModel tableModel = new CustomTableModel();
        JXXTable table = new JXXTable(tableModel);
        JScrollPane scrollPane = new JScrollPane(table);
        SelectionListener listener = new SelectionListener(table);
        table.getSelectionModel().addListSelectionListener(listener);    
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
        frame.add(scrollPane);
        frame.setVisible(true);
        frame.pack();
    }
}

class JXXTable extends JXTable {
    public JXXTable(CustomTableModel model){ super(model); }
    public void Paint(){
        this.setDefaultRenderer(Object.class, new DefaultTableCellRenderer());
        this.setHighlighters();
        HighlightPredicate predicate = new HighlightPredicate() {
            public boolean isHighlighted(Component renderer, ComponentAdapter adapter) {
                return adapter.hasFocus();
            }
        };
        this.addHighlighter(new ColorHighlighter(predicate, null, null, new Color(115,164,209), Color.WHITE)); 
    }
}

class SelectionListener implements ListSelectionListener {
    JXXTable table;
    public SelectionListener(JXXTable table) { this.table = table; }
    public void valueChanged(ListSelectionEvent e) { table.Paint(); }
}

class CustomTableModel extends AbstractTableModel {
    ArrayList<Object[]> al;

    public CustomTableModel() {
        al = new ArrayList<Object[]>(); 
        Object[] row = {1,2,3,"A","Collection","of","Random","Strings",9,10}; al.add(row);
        Object[] row2 = {11,12,13,"Another","Collection","Of","Random","Strings",19,20}; al.add(row2);
        Object[] row3 = {11,12,13,"Another","Collection","Of","Random","Strings",19,20}; al.add(row3);
        Object[] row4 = {11,12,13,"It","just","gets","more","random...",19,20}; al.add(row4);
    }

    public int getRowCount() { return al.size(); }
    public int getColumnCount() { return 10; }
    public Object getValueAt(int rowIndex, int columnIndex) { return al.get(rowIndex)[columnIndex]; }
}

2 ответа

Решение

Для других, имеющих эту проблему, это было мое решение.

Проблема заключалась в том, что новый объект TableCellRenderer создавался при каждом вызове метода Paint() таблицы (т. Е. При каждом изменении выбора). Решение состояло в том, чтобы создать объект визуализации как поле объекта таблицы и просто повторно применить его (а не заново создать) в методе Paint(). Этот рендер также нужно было применять во время конструктора таблицы.

Еще одно усовершенствование кода, которое я сделал во время этого процесса, заключалось в применении того же правила выше к объектам ColorHighlighter и HighlightPredicate.

то есть. класс таблицы становится:

class JXXTable extends JXTable {
    DefaultTableCellRenderer renderer = new DefaultTableCellRenderer();
    HighlightPredicate predicate = new HighlightPredicate(){
        public boolean isHighlighted(Component renderer, ComponentAdapter adapter) {
            return adapter.hasFocus();
        }
    };
    Highlighter cellHighlight = new ColorHighlighter(predicate, null, null, new Color(115,164,209), Color.WHITE);

    public JXXTable(CustomTableModel model){ 
        super(model); 
        this.setDefaultRenderer(Object.class, renderer);
    }
    public void Paint(){
        this.setDefaultRenderer(Object.class, renderer);
        this.setHighlighters();
        this.addHighlighter(cellHighlight); 
    }
}

Я "думаю", что часть проблемы связана с тем, что вы добавляете ДРУГОЙ маркер каждый раз, когда выбор меняется.

Вместо этого рассмотрите возможность добавления выделения только при инициализации таблицы...

Сказав это, также нет необходимости расширять JXTableвы не добавляете никакой новой функциональности в класс. Вместо этого вы можете создать какую-то фабрику, которая сконфигурировала бы ту таблицу, которую вы хотите

import java.awt.Color;
import java.awt.Component;
import java.awt.EventQueue;
import java.util.ArrayList;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
import javax.swing.table.AbstractTableModel;
import javax.swing.table.DefaultTableCellRenderer;
import org.jdesktop.swingx.JXTable;
import org.jdesktop.swingx.decorator.ColorHighlighter;
import org.jdesktop.swingx.decorator.HighlightPredicate;

public class MainClass {

    public static void main(String[] args) {
        new MainClass();
    }

    public MainClass() {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                JFrame frame = new JFrame();
                CustomTableModel tableModel = new CustomTableModel();
                JXTable table = new JXTable(tableModel);
                table.setDefaultRenderer(Object.class, new CustomTableCellRenderer());
                HighlightPredicate predicate = new HighlightPredicate() {
                    @Override
                    public boolean isHighlighted(Component cmpnt, org.jdesktop.swingx.decorator.ComponentAdapter ca) {
                        System.out.println(ca.getComponent());
                        return ca.hasFocus();
                    }
                };
                table.addHighlighter(new ColorHighlighter(predicate, null, null, new Color(115, 164, 209), Color.WHITE));

                JScrollPane scrollPane = new JScrollPane(table);
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame.add(scrollPane);
                frame.setVisible(true);
                frame.pack();
            }
        });
    }

    class CustomTableCellRenderer extends DefaultTableCellRenderer {

        public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
            return (JLabel) super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);
        }
    }

    class CustomTableModel extends AbstractTableModel {

        ArrayList<Object[]> al;

        public CustomTableModel() {
            al = new ArrayList<Object[]>();
            Object[] row = {1, 2, 3, "A", "Collection", "of", "Random", "Strings", 9, 10};
            al.add(row);
            Object[] row2 = {11, 12, 13, "Another", "Collection", "Of", "Random", "Strings", 19, 20};
            al.add(row2);
            Object[] row3 = {11, 12, 13, "Another", "Collection", "Of", "Random", "Strings", 19, 20};
            al.add(row3);
            Object[] row4 = {11, 12, 13, "It", "just", "gets", "more", "random...", 19, 20};
            al.add(row4);
        }

        public int getRowCount() {
            return al.size();
        }

        public int getColumnCount() {
            return 10;
        }

        public Object getValueAt(int rowIndex, int columnIndex) {
            return al.get(rowIndex)[columnIndex];
        }
    }
}
Другие вопросы по тегам