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

#swing #background #jtable

#swing #фон #jtable

Вопрос:

Привет всем,

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

Однако на данный момент у меня есть 2 проблемы:
1) Ячейки отображаются не сразу, а после всего цикла итерации
2) Области не отображаются должным образом — если мне нужно нарисовать таблицу [3, 4] и таблицу [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.");
     }
 }
  

Есть какие-нибудь советы по этому поводу?

Комментарии:

1. пожалуйста, попробуйте исправить форматирование (теги кода здесь не работают / не нужны): отступа в 4 символа достаточно

Ответ №1:

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

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

Лучше всего прочитать руководство 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) 
  

Комментарии:

1. Привет, клеопатра, спасибо за твое критическое мнение — это очень помогает. Я определенно согласен с вашими рекомендациями. Однако я попробовал манипулировать моделью как внутри модели, так и за ее пределами, из демо-версии с JTable внутри, а также с средством визуализации. Я просто пытаюсь вызвать события из разных действий. Однако ваше мнение абсолютно верно вне контекста, и я действительно ценю. Тестирую вашу демо-версию прямо сейчас.

2. Я внес некоторые изменения в свой код, основываясь на вашем совете выше. Однако дело в следующем — данные таблицы статичны, мне нужно запустить JButton, который повторяет мою таблицу и окрашивает там, где это необходимо. Мой рендерер зарегистрирован по умолчанию для таблицы, но обновлений нет. Еще раз спасибо за помощь.

3. @Mario тривиально что-то должно измениться (иначе вы бы не захотели перекрашивать). Инкапсулируйте это «что-то» вместе со статической датой в вашей табличной модели и дайте модели сработать, если «что-то» изменится

4. моей ошибкой было установить цвет средства визуализации один раз и пропустить часть normalColor. Теперь средство визуализации работает нормально. Кроме того, я запускаю поток для рисования, чтобы иметь возможность рисовать букву за буквой. Спасибо за ваши советы.