【问题标题】:Revalidating JList - custom elements重新验证 JList - 自定义元素
【发布时间】:2012-03-13 14:01:34
【问题描述】:

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

看起来像这样:

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

当您单击隐藏(或显示,这是一个切换)时,它应该像这样最小化元素......

唯一的问题是......它不会更新 JList 单元格大小,因为您可以看到文本曾经所在的大空白区域。
但是,当我键入另一条消息时...

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

【问题讨论】:

  • 请学习java命名约定并遵守它们
  • 我知道java命名约定,我只是喜欢我的swing变量大写。但我也不总是遵循这一点......

标签: java swing jpanel jlist custom-renderer


【解决方案1】:

这是JTable 的工作,在TableModel 中有两列(ChatBoolean),并且只有可见的Chat 列,诀窍是通过实现RowFilter 使用您设置为第二列的参数仅String "false"JTable 中的ObjectBoolean 可以通过String "true" / "false" 中的返回值进行过滤)

【讨论】:

  • 您的语法使您的答案难以理解。这个 JTable 将如何修复单元格大小调整?你必须记住我正在使用自定义单元格渲染器来渲染这个 JList。没有它,它不会显示它所做的事情。
  • @Bradley Odell 请阅读教程JList 关于模型(存储数据)和视图及其渲染,不要永远不要使用 invalidate()
【解决方案2】:

没有看到任何代码,我只能猜测:最可能的原因是您在列表的脚下进行隐藏,即没有其模型通知其听众。列表的 ui 委托将单元格大小缓存在深处,在接收到 ListEvents 时将其清除

【讨论】:

  • 你认为我在JList 下方用鼠标右键单击并隐藏元素?当我“隐藏”元素时发生的所有事情都是 JTextArea(保存聊天消息)被设置为不可见。因此,当它的可见性发生变化时,我需要 JList 重新计算该元素的单元格大小。
【解决方案3】:

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

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

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

我偶然发现了这个问题,因为我的项目代码最初是为了调用ListModelremoveAllElements() 方法而编写的,然后使用addElement() 再次将所有元素一一添加。一切都很好,直到我决定我应该重写程序,以便只要用户请求更改 JList 中显示组件的尺寸,它就可以简单地保留模型。换句话说,没有必要涉及模型,因为没有从列表中添加或删除元素。不幸的是,在更改渲染器的首选大小后,对JList 的任何repaint()revalidate() 方法调用都不会导致它正确布局其元素。就我而言,仅调整父组件(JFrame)的大小会产生预期的行为。

【讨论】:

    猜你喜欢
    • 2014-06-18
    • 1970-01-01
    • 1970-01-01
    • 2017-12-30
    • 1970-01-01
    • 1970-01-01
    • 2020-07-24
    • 2011-12-09
    • 2021-02-20
    相关资源
    最近更新 更多