重新验证JList - 自定义元素

时间:2012-02-23 06:50:37

标签: java swing jpanel jlist custom-renderer

我正在使用JList来保存聊天程序的聊天数据 它使用自定义列表渲染器将自定义JPanel对象呈现为元素类型 这个JPanel包含两个JLabel(固定在顶部,用于名称和时间),以及一个JTextArea(锚定在底部,用于聊天消息)。

看起来像这样:

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

一切都很好,但我想添加隐藏/显示功能 使用以前编程的PopupMenu处理程序,当您右键单击元素时,会出现一个弹出窗口。

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

当你点击隐藏(或显示,它是一个切换),那么它应该像这样最小化元素......

a pic3 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 个答案:

答案 0 :(得分:3)

没有看到任何代码,我只能猜测:最可能的原因是你在列表的脚下做了隐藏,没有它的模型通知它的听众。列表的ui委托缓存内部的单元格大小,在接收ListEvents

时清除

答案 1 :(得分:2)

这是JTable的工作,Chat中有两个列(BooleanTableModel)且仅有Chat列,诀窍是使用工具RowFilter进行操作,您只需String "false" Object JTable Boolean String "true" / "false" {{1}},{{1}}可以使用{{1}}进行过滤。 {{1}})

答案 2 :(得分:0)

这是JList班级的一个非常特殊的缺点。我在清理不相关领域的一些代码的过程中遇到了这个问题。

对于它的价值,从ListModel中删除元素然后再添加它将为JList中的关联渲染组件生成适当的尺寸。这是一个奇怪的方法,似乎导致列表的行为与接受(和首选)的解决方案相同:

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

我偶然发现了这个问题,因为我的项目代码最初用于调用removeAllElements()的{​​{1}}方法,然后使用ListModel逐个添加所有元素。一切都工作得很好,直到我决定我应该重写程序,这样只要用户请求更改JList中显示的组件的维度,它就会单独留下模型。换句话说,没有必要涉及模型,因为没有从列表中添加或删除元素。遗憾的是,在更改渲染器的首选大小后,addElement()上的repaint()revalidate()方法调用量不会导致其正确布局其元素。在我的例子中,只调整父组件(JList)的大小会产生预期的行为。