Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Revalidating JList - custom elements

I'm using a JList to hold chat data for my chat program.
It uses a custom list renderer to render a custom JPanel object as the element type.
This JPanel contains two JLabels (anchored to the top, for name and time), and a JTextArea (anchored to the bottom, for chat message).

It looks like this:

a pic1

Everything works great, but I want to add a hide/show feature.
Using a previously programmed PopupMenu handler, I have a popup appear when you right click on an element.

a pic2

When you click hide (or show, it's a toggle) then it should minimize the element like so...

a pic3

The only problem is... it doesn't update the JList cell size as you can see the large empty region where the text used to be.
However, when I type another message...

a pic4

The JList fixes the cell size completing the 'hide' operation.
My question is how do you get the JList to revalidate/repaint/etc programmatically.
And don't think I haven't tried all the obvious solutions...

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();
}

The custom JPanel class uses a GroupLayout to render the components.
Do you guys have any knowledge on how to programmically cause a JList to revalidate its cell sizes?
... besides the methods that I've posted? :)

Solution:
After searching method after method and testing if they would solve my problem, I found that executing this code after a hide/show operation would cause the cell height (and width) to be recalculated and without any unwanted visual 'flicker' of the JList.

list.setFixedCellHeight(0);
list.setFixedCellWidth(0);
list.setFixedCellHeight(-1);
list.setFixedCellWidth(-1);
like image 914
Bradley Odell Avatar asked Feb 23 '12 06:02

Bradley Odell


2 Answers

Without seeing any code, I can only guess: the most probable reason is that you're doing the hide under the feet of the list, that is without its model notifying its listeners. The list's ui delegate caches the cell size deep inside, which is cleared on receiving ListEvents

like image 189
kleopatra Avatar answered Oct 26 '22 01:10

kleopatra


This is job for JTable with two Columns (Chat and Boolean) in the TableModel and with visible Chat Column only, the trick is by using by implement RowFilter where you set as parameter to the second column only String "false" (Object in the JTable with Boolean is possible filtering with returns value in the String "true" / "false")

like image 2
mKorbel Avatar answered Oct 26 '22 01:10

mKorbel