【问题标题】:JLabel within JTree won't resize when content changes内容更改时,JTree 中的 JLabel 不会调整大小
【发布时间】:2013-10-24 22:11:19
【问题描述】:

我有一个行为如下的 JTree:

  • 根有一个RootObject类型的用户对象;它使用纯文本标签,并且在树的整个生命周期内都是静态的。
  • 每个孩子都有一个ChildObject 类型的用户对象,它可能处于以下三种状态之一:未运行、正在运行或已完成。
  • ChildObject 未运行时,为明文标签。
  • ChildObject 运行时,它使用图标资源并切换到 HTML 呈现,因此文本为斜体。
  • ChildObject 完成后,它使用不同的图标资源并使用 HTML 呈现以粗体显示文本。

目前,我的代码如下所示:

public class TaskTreeCellRenderer extends DefaultTreeCellRenderer {
    private JLabel label;

    public TaskTreeCellRenderer() {
        label = new JLabel();
    }

    public Component getTreeCellRendererComponent(JTree tree,
           Object value, boolean selected, boolean expanded, boolean leaf, int row, boolean hasFocus) {
        Object nodeValue = ((DefaultMutableTreeNode) value).getUserObject();

        if (nodeValue instanceof RootObject) {
            label.setIcon(null);
            label.setText(((RootObject) nodeValue).getTitle());
        } else if (nodeValue instanceof ChildObject) {
            ChildObject thisChild = (ChildObject) nodeValue;

            if (thisChild.isRunning()) {
                label.setIcon(new ImageIcon(getClass().getResource("arrow.png")));
                label.setText("<html><nobr><b>" + thisChild.getName() + "</b></nobr></html>");
            } else if (thisChild.isComplete()) {
                label.setIcon(new ImageIcon(getClass().getResource("check.png")));
                label.setText("<html><nobr><i>" + thisChild.getName() + "</i></nobr></html>");
            } else {
                label.setIcon(null);
                label.setText(thisChild.getName());
            }
        }

        return label;
    }
}

在大多数情况下,这渲染得很好。使用纯文本的标签可以很好地呈现初始树。问题是一旦ChildObject 实例开始改变状态,JLabels 就会更新为使用 HTML 呈现,但不会调整大小以补偿文本或图标。例如:

初始状态:
http://imageshack.us/a/img14/3636/psxi.png

进行中:
http://imageshack.us/a/img36/7426/bl8.png

已完成:
http://imageshack.us/a/img12/4117/u34l.png

任何想法我哪里出错了?提前致谢!

【问题讨论】:

  • 看起来树的更新错误。更改图标后,您必须告诉树模型已更改。
  • label.setText("&lt;html&gt;&lt;nobr&gt;&lt;b&gt;.. 尝试不使用 HTML。如需尽快获得更好的帮助,请发帖SSCCE
  • 可能相关(或不相关,没有 SSCCE 就无法判断):您的渲染器看起来很可疑 - 它 扩展 默认(又名:is-a 标签),has-a标签字段,在两个 if 块中重新创建新标签并返回该字段...无论如何,我的赌注与@SergiyMedvynskyy 相同 - 很可能是更改通知不正确
  • @Kleopatra:这主要是我尝试不同的想法来解决问题。最初的实现没有在 if 子句中创建新的 JLabel,并且仍然存在这个问题。我已经编辑了代码以反映这一点。

标签: java swing jlabel jtree treecellrenderer


【解决方案1】:

所以你需要告诉树模型内容发生了变化。 每次如果您的 ChildObject 的状态发生更改,您必须执行以下操作:

((DefaultTreeModel)tree.getModel()).reload(node);

其中nodeDefaultMutableTreeNode,其中包含更改后的 ChildObject。

如果子对象的状态在 Swing-Thread (EDT) 之外更改,请不要忘记使用 SwingUtilities.invokeLater()。

【讨论】:

  • ...可能不会:仅当更改非常分散且不适合更集中的事件时才需要重新加载。
  • 就是这样!回想起来,这似乎很明显,但当时我并没有想到。谢谢!我应该提一下,我没有使用 reload(node),而是使用了标准的 reload() 方法,因为我的程序不知道哪些 ChildObjects 改变了它们的状态。它可能可以,但那是为了以后的重构。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2012-03-23
  • 1970-01-01
  • 1970-01-01
  • 2013-07-10
  • 1970-01-01
  • 2014-04-15
  • 2012-07-24
相关资源
最近更新 更多