Swing JTable - невозможно перекрасить и изменить фон ячеек

Привет всем,

Я пытаюсь сделать некоторые вычисления в JTable после итерации и пометить другим фоном нужные мне ячейки.

Однако на данный момент у меня есть 2 проблемы:
1) Ячейки закрашиваются не сразу, а после всего цикла итерации
2) Области не закрашиваются должным образом - если мне нужно закрасить table[3, 4] и table[6, 5] он рисует прямоугольник от [3,4] до [6, 5] вместо того, чтобы рисовать только отдельные ячейки.

О проблеме 1: могу ли я вызвать repaint() с приоритетом без необходимости заканчивать все и JVM решать, когда рисовать? Я пытаюсь сделать fireTableCellUpdated() и fireTableDataChanged(), но они не обновляются.

Вот мой пользовательский метод рендеринга ячеек, который изменяет BGcolor:

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

    if(value instanceof Color) {
        Color c = (Color) value;
        renderer.setBackground(c);
        System.out.println("BG change [" + row + ":" + column + "]");
    }

    return renderer;
}

Здесь есть цикл, в котором я рисую свои ячейки по нажатию кнопки:

for(int paintJ = startIndex; paintJ < endIndex; paintJ++) {
     CrossCellRenderer rend =  (CrossCellRenderer) jTable1.getCellRenderer(i,  paintJ)
           .getTableCellRendererComponent(jTable1, Color.blue, true, true, i, paintJ);
     crossTableModel.fireTableCellUpdated(i, paintJ);
     jTable1.revalidate();
     jTable1.repaint();
     try {
          Thread.sleep(1000);
     }   catch(InterruptedException ie) {
           System.err.println("Exception sleeping the thread.");
     }
 }

Любые советы по этому поводу?


person Mario Peshev    schedule 30.04.2011    source источник
comment
пожалуйста, попробуйте исправить форматирование (кодовые теги здесь не работают/не нужны): достаточно отступа в 4 символа   -  person kleopatra    schedule 30.04.2011


Ответы (1)


Ненавижу говорить: но вы делаете это (чего бы вы ни хотели) совершенно неправильно ;-)

  • Никогда не выполняйте какие-либо прямые манипуляции или рисование в средстве визуализации, вместо этого измените данные model, а все остальное произойдет автоматически.
  • Никогда не вызывайте какие-либо методы fireXX для модели из-за пределов модели, это исключительная ответственность модели за уведомление своих слушателей об изменении.
  • Никогда (или очень-очень редко, уж точно не здесь ;-) нет необходимости вызывать revalidate и/или перекрашивать напрямую, это произойдет автоматически, если модель ведет себя хорошо
  • ....

Лучше всего прочитать учебник Snoracle по использованию таблиц, чтобы полностью понять механизм рендеринга.

http://download.oracle.com/javase/tutorial/uiswing/components/table.html

Грубо:

   // change the model, will notify its listeners
   model.setValueAt(....)

   // in a custom renderer, check the value and decorate as appropriate
   public Component getTableCellRendererComponent(....) {
        // ... normal config, f.i. done in super
        Component comp = super.get...
        if (myConditionForSpecialColor(table, value, ...) {
            comp.setBackground(myColor);
        } else {
            comp.setBackground(normalColor);
        }
   }

   // register the custom renderer 
   // per class
   table.setDefaultRenderer(Object.class, myRenderer)
   // or per column
   table.getColumnModel().getColumn(myColumn).setCellRenderer(myRenderer) 
person kleopatra    schedule 30.04.2011
comment
Здравствуйте, kleopatra, спасибо за ваше критическое мнение - очень помогает. Я определенно согласен с вашими лучшими практиками. Однако я пробовал манипулировать моделью внутри и снаружи модели, из демо с jTable и рендерером. Я просто пытаюсь вызвать события из разных действий. Однако ваше мнение абсолютно верно вне контекста, и я действительно ценю его. Тестируем демо прямо сейчас. - person Mario Peshev; 30.04.2011
comment
Я сделал некоторые изменения в своем коде на основе вашего совета выше. Однако дело в следующем: данные таблицы статические, мне нужно вызвать JButton, который повторяет мою таблицу и цвета, где это необходимо. Мой рендерер зарегистрирован по умолчанию для таблицы, но не обновляется. Спасибо еще раз за помощь. - person Mario Peshev; 30.04.2011
comment
@Mario тривиально что-то должен изменить (иначе вы бы не захотели перекрашивать). Инкапсулируйте это что-то вместе со статической датой в вашей TableModel и позвольте модели сработать, если что-то изменится. - person kleopatra; 30.04.2011
comment
моя ошибка заключалась в том, что я один раз установил цвет рендерера и пропустил часть normalColor. Теперь рендер работает нормально. Кроме того, я запускаю нить для рисования, чтобы иметь возможность рисовать букву за буквой. Спасибо за ваши советы. - person Mario Peshev; 02.05.2011