【问题标题】:Flashing while reloading JTree重新加载 JTree 时闪烁
【发布时间】:2012-06-19 00:59:53
【问题描述】:

我正在制作一个经常更新JTree 的模拟器。树中的节点都是JProgressBars

我正在调用 tree.treeModel.insertNodeInto(,,)treeModel.reload() 来更新树。问题是它会立即更新自己而无需等待repaint() 调用。这会导致树闪烁。我尝试为节点、树和它所在的容器设置setDoubleBuffered(true),但没有任何变化。

这是我的代码:(班级File extends DefaultMutableTreeNode

public class FileTree extends JTree {

    DefaultTreeModel myTreeModel;

    FileTree(File root) {
        super(root);
        myTreeModel = (DefaultTreeModel) this.getModel();
        this.treeModel = myTreeModel;
        this.setCellRenderer(new ProgressBarCellRenderer());
        this.setEditable(true);
    }

    public void update(File file, File parent) {
        myTreeModel.insertNodeInto(file, parent, parent.getChildCount());
        myTreeModel.reload();
    }

    class ProgressBarCellRenderer extends DefaultTreeCellRenderer {
        public Component getTreeCellRendererComponent(JTree tree, Object value,
                boolean selected, boolean expanded, boolean leaf, int row, boolean hasFocus) {
            File file = (File) value;
            JProgressBar progressBar;
            progressBar = new JProgressBar(0, file.length);
            progressBar.setValue(file.completed);
            progressBar.setPreferredSize(new Dimension((int)(Math.log(file.size)*50),10));
            return progressBar;
        }
    }

}

【问题讨论】:

  • 也许吧。但我不太关心性能,因为整体更新率足够小。我只想在重新加载时摆脱闪光灯/闪烁。缓冲区应该这样做。但我不知道如何以简单的方式做到这一点。
  • insertNodeInto 之后无需再调用reload()insertNodeInto 内部调用 fireTreeNodesInserted 进而更新树。

标签: java swing rendering jtree double-buffering


【解决方案1】:

我怀疑是mixing heavy and light components 导致了闪烁。在这个example 中可以通过单击圆圈或调整包围框架的大小来看到效果。为了获得更好的指导,请编辑您的问题以包含一个 sscce 来展示您所描述的问题。

【讨论】:

  • 感谢 sscce 的建议。我会做到的。但这似乎工作量太大了,因为现在问题已经解决了。
【解决方案2】:

我修好了。我刚换了

myTreeModel.insertNodeInto(file, parent, parent.getChildCount());

parent.add(file);

我不知道为什么它现在有效。但确实如此。任何 cmet 都表示赞赏!

【讨论】:

  • parent.add(file) 破坏了基于模型的更新逻辑 - 您只将新组件添加到视图中,并且需要手动更新 UI。
【解决方案3】:

我在使用自定义渲染器时遇到了同样的问题。

只需在SwingUtilities.invokeLater 内进行更新

SwingUtilities.invokeLater(new Runnable() {
        @Override
        public void run() {
            myTreeModel.insertNodeInto(file, parent, parent.getChildCount());
        }

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2016-06-05
    • 2023-03-22
    • 1970-01-01
    • 2017-07-19
    • 2013-10-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多