Повторная проверка JList - пользовательские элементы - PullRequest
5 голосов
/ 23 февраля 2012

Я использую JList для хранения данных чата для моей программы чата.
Для визуализации пользовательского объекта JPanel в качестве типа элемента используется настраиваемое средство отображения списка.
Этот JPanel содержит две метки JLabel (привязанные к началу, для имени и времени) и JTextArea (привязанные к нижней части, для сообщения чата).

Это выглядит так:

a pic1 http://oi44.tinypic.com/20jiix5.jpg

Все отлично работает, но я хочу добавить функцию скрытия / показа.
Используя ранее запрограммированный обработчик PopupMenu, у меня появляется всплывающее окно, когда вы щелкаете правой кнопкой мыши по элементу.

a pic2 http://oi42.tinypic.com/2m5exxt.jpg

Когда вы нажимаете кнопку скрыть (или показать, это переключение), тогда элемент должен минимизироваться следующим образом:

рис3 http://oi41.tinypic.com/kf3apx.jpg

Единственная проблема ... он не обновляет размер ячейки JList, так как вы видите большую пустую область, где раньше был текст.
Однако, когда я набираю другое сообщение ...

a pic4 http://oi40.tinypic.com/35jdoo7.jpg

JList фиксирует размер ячейки, выполняя операцию «скрыть».
Мой вопрос заключается в том, как заставить JList выполнить повторную проверку / перерисовку / и т.д. программным способом.
И не думайте, что я не пробовал все очевидные решения ...

public void setHidden(boolean hidden) {
    // this is in the custom JPanel class
    System.out.println("Initial: " + this.getPreferredSize());

    // TextArea is the JTextArea which we set invisible when we want to hide it.
    TextArea.setVisible(!hidden); // TextArea is a variable btw
    this.invalidate();
    this.validate();
    this.repaint();

    System.out.println("After: " + this.getPreferredSize());
    container.revalidate();
}

/*
 * This is what the above printlns show when you hide, then show the element.
 *
 * Initial: java.awt.Dimension[width=176,height=38]
 * After: java.awt.Dimension[width=176,height=20]
 * Initial: java.awt.Dimension[width=176,height=20]
 * After: java.awt.Dimension[width=176,height=38]
 */

public void revalidate() {
    // container.revalidate() ^^^
    // list is the list containing the chat elements
    list.invalidate();
    list.validate();
    list.repaint();
}

Пользовательский класс JPanel использует GroupLayout для визуализации компонентов.
Ребята, у вас есть какие-либо знания о том, как программно заставить JList повторно проверять размеры его ячеек?
... кроме методов, которые я опубликовал? :)

Решение:
После поиска метода за методом и тестирования, решат ли они мою проблему, я обнаружил, что выполнение этого кода после операции скрытия / показа приведет к пересчету высоты (и ширины) ячейки без какого-либо нежелательного визуального «мерцания» JList.

list.setFixedCellHeight(0);
list.setFixedCellWidth(0);
list.setFixedCellHeight(-1);
list.setFixedCellWidth(-1);

Ответы [ 3 ]

3 голосов
/ 23 февраля 2012

Не видя никакого кода, я могу только догадываться: наиболее вероятная причина в том, что вы делаете скрытие под ногами списка, то есть без его модели, уведомляющей слушателей.Пользовательский делегат списка глубоко кэширует размер ячейки, который очищается при получении ListEvents

2 голосов
/ 23 февраля 2012

Это задание для JTable с двумя столбцами (Chat и Boolean) в TableModel и только с видимыми Chat только столбцами, хитрость заключается в использовании RowFilter где вы устанавливаете в качестве параметра только для второго столбца String "false" (Object в JTable с Boolean возможна фильтрация с возвращаемым значением в String "true" / "false")

0 голосов
/ 19 июля 2014

Это очень специфический недостаток класса JList. Я сам столкнулся с проблемой в ходе очистки части моего кода в несвязанных областях.

Для чего стоит удалить элемент из ListModel и затем добавить его снова, получится соответствующий размер для связанного визуализируемого компонента в JList. Это странный способ сделать это, и кажется, что список ведет себя так же, как принятое (и предпочтительное) решение:

list.setFixedCellHeight(0);
list.setFixedCellWidth(0);
list.setFixedCellHeight(-1);
list.setFixedCellWidth(-1);

Я наткнулся на эту проблему, потому что код для моего проекта изначально был написан для вызова removeAllElements() метода ListModel, а затем снова добавил все элементы один за другим, используя addElement(). Все работало замечательно, пока я не решил, что мне следует переписать программу, чтобы она просто оставляла модель в покое всякий раз, когда пользователь запрашивал изменения размеров отображаемых компонентов в JList. Другими словами, нет необходимости привлекать модель, поскольку элементы не добавляются и не удаляются из списка. К сожалению, после изменения предпочтительного размера рендерера никакие вызовы методов repaint() или revalidate() для JList не приведут к правильному расположению его элементов. В моем случае только изменение размера родительского компонента (JFrame) привело к намеченному поведению.

...