2012-02-23 66 views
5

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

它看起来像这样:

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单元格大小,因为您可以看到文本曾经是大的空白区域。
然而,当I型的另一消息......

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

JList的固定单元尺寸完成“隐藏”操作。
我的问题是如何让JList以编程方式重新验证/重新绘制/ etc。
不要以为我没有试过所有的解决方案明显...

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); 
+0

请学习java命名约定并坚持到他们 – kleopatra 2012-02-23 09:55:57

+0

我知道java的命名约定,我只是想让我的swing变量大写。但我并不总是遵循这一点...... – 2012-02-23 21:38:20

回答

2

这是JTable与在TableModel和可见Chat列两列(ChatBoolean)作业只,关键是通过使用实现RowFilter,你作为参数设置为第二列只String "false" (在JTableBooleanObject是在String "true"/"false"返回值可以过滤)

+0

你的语法让你的答案难以理解。这个JTable将如何修复单元格大小调整?你必须记住我正在使用自定义的单元格渲染器来渲染这个JList。如果没有它,它将不会显示它的功能。 – 2012-02-23 21:47:47

+0

@Bradley Odell请阅读教程[JList](http://docs.oracle.com/javase/tutorial/uiswing/components/list.html)关于模型(有数据存储)和视图及其渲染,而不是从来没有't use invalidate() – mKorbel 2012-02-23 22:18:45

3

没有看到任何代码,我只能猜测:最可能的原因是你下的L的脚做皮这是没有其模型通知其听众。该列表的用户代理将单元格大小缓存在内部,在接收ListEvents时清除。

+0

你认为我是右键单击并将物理元素隐藏在JList的物理下方吗?当我“隐藏”元素时发生的所有事情是JTextArea(持有聊天消息)被设置为不可见。所以当它的可见性发生变化时,我需要JList重新计算它的单元大小。 – 2012-02-23 21:50:46

0

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

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

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

我偶然发现了这个问题,因为我的项目代码原文调用ListModelremoveAllElements()方法,然后使用addElement()逐个添加所有元素。一切工作都很好,直到我决定重写程序,以便只要用户请求JList中显示组件的尺寸更改时,它就会让模型独立。换句话说,没有必要牵涉到模型,因为元素没有被添加或从列表中删除。不幸的是,在更改渲染器的首选大小后,或revalidate()方法调用JList将导致它正确地布局其元素。在我的情况下,只调整父组件(一个JFrame)产生了预期的行为。