Почему мой JTable CellRenderer работает все время?

// вопрос новичка

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

Так оно и должно быть? Разве он не должен был визуализировать каждую ячейку один раз, и все? Как я могу остановить его и пересчитывать только при изменении?

public Component getTableCellRendererComponent(JTable table, Object value,
    boolean isSelected, boolean hasFocus, int row, int column) {

   log.debug("Building cell : " + row + "," + column);

   Component comp = super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);

   Filter filter = (Filter)table.getModel().getValueAt(row, Column.CLASSIFICATION.getIndex());
   comp.setBackground(filter.getColor());
   return comp;

  }

person Yossale    schedule 27.12.2010    source источник
comment
Это неправильное поведение. Можете ли вы создать автономный пример кода, демонстрирующий это? Это поможет нам решить эту проблему.   -  person Steve McLeod    schedule 27.12.2010
comment
@ Стив, я думаю, это будет слишком много кода. Я только что узнал, что у меня есть другое средство визуализации для определенных ячеек в таблице. Неужели они увольняют друг друга?   -  person Yossale    schedule 27.12.2010
comment
Это могло быть что угодно. Психическая отладка - это сложно. Просто основной метод, который создает JFrame, добавляет таблицу, устанавливает средство визуализации ячеек, подобное тому, которое вы уже показали, и имеет ту же проблему.   -  person Steve McLeod    schedule 27.12.2010
comment
Обратите внимание, что когда ваша таблица отсортирована, вы получите неправильный Filter из своей модели. row, который передается в качестве аргумента, находится в «координатах табличного представления», а не в «координатах модели».   -  person Robin    schedule 05.10.2012


Ответы (4)


Я работал много с JTables, содержащим много данных. Больше, чем то, чем обычно манипулируют 99,9% программистов на Java. Вам нужно знать одну вещь: по умолчанию образуется безумное количество отходов и безумное количество, как правило, ненужных операций.

Если вам нужны быстрые и эффективные JTables, то есть авторитетная статья Sun на эту тему:

«Новогодние приложения, как создавать часто обновляемые таблицы JTable, которые хорошо работают»

Обратите внимание на «которые хорошо работают» в заголовке, потому что по умолчанию перфомансы JTable действительно ужасно плохи:

Исходная ссылка (Sun)

Текущая ссылка (Oracle)

Архивная версия: < / а>

После реализации двух или трех методов, рекомендованных в этой статье, вы заметите удивительное ускорение рендеринга JTable и заметите, что создается гораздо меньше мусора (и, следовательно, сборщик мусора должен работать реже).

person SyntaxT3rr0r    schedule 27.12.2010
comment
Добавлена ​​ссылка на архив для страницы ChristmasTree, так как исходная ссылка мертва. Он появится после того, как мое изменение будет рассмотрено. - person bohney; 05.10.2012
comment
Перфомансы JTable действительно ужасно плохи, если бы это было правдой, после плохой (для производственного кода) короткой отрисовки идей в статье ничего не изменится: она даже не улучшится на на порядок ;-) - person kleopatra; 05.10.2012

Следуя предложению @Steve McLeod, я начал создавать пример кода с той же ошибкой, и только тогда я понял, что внутри одного из моих CellRenderers

@Override
    public Component getTableCellRendererComponent(JTable table, Object value,
            boolean isSelected, boolean hasFocus, int row, int column) {

        log.debug("Building a list for " + row + "," + column);
        setListData(((Vector<String>)value).toArray());     
        setToolTipText("This is a tool tip for " + row + "," + column);

        table.setRowHeight(row, Math.max(1, getPreferredSize().height));
        Filter filter = (Filter)table.getModel().getValueAt(row, Column.CLASSIFICATION_RESULT.getIndex());
        setBackground(filter.getColor());       
        return this;
    }

У меня была строчка:

table.setRowHeight(row, Math.max(1, getPreferredSize().height));

и он постоянно менял строку строки, в то время как другие рендеры в той же строке делали то же самое ... поэтому они постоянно запускали друг друга.

person Yossale    schedule 29.12.2010

Я заметил, что вы меняете внешний вид ячейки в зависимости от значения другой ячейки. Если эта связь идет в обе стороны - внешний вид ячейки 1 основан на ячейке 2, и наоборот, вы можете получить такую ​​проблему. Но на самом деле нам нужен автономный пример кода, который воспроизводит проблему - иначе мы сможем стрелять только в темноте.

person Steve McLeod    schedule 27.12.2010

средство визуализации уже кэширует ваш визуализированный компонент, когда ничего не меняется, ничего не перерисовывается

Однако, когда таблица обнаруживает, что что-то МОЖНО изменить, она запросит повторную визуализацию. Событие, которое вызывает его больше всего, - это движение мыши.

Так что да, это нормальное поведение для JTable.

person Peter    schedule 27.12.2010
comment
Я так думал, но это не то, что происходит: когда таблица находится на экране, а мышь не движется, я все еще вижу, что сообщения журнала работают как сумасшедшие - person Yossale; 27.12.2010
comment
это нормально, потому что реализация JTable по умолчанию действительно плохая. В статье, на которую я ссылаюсь, также объясняется, как добиться нормального и быстрого поведения для часто обновляемых JTables. - person SyntaxT3rr0r; 27.12.2010
comment
Непрерывный вызов средства визуализации, когда пользователь ничего не делает с мышью или таблицей, НЕ является нормальным явлением. У вас есть код в вашей программе, который должен зацикливаться или что-то в этом роде. Опубликуйте свой SSCCE (sscce.org), демонстрирующий проблему. - person camickr; 27.12.2010