0

I am making a simulator with a JTree updating frequently. The nodes in the tree are all JProgressBars.

I'm calling tree.treeModel.insertNodeInto(,,) and treeModel.reload() to update the tree. the problem is that it instantly updates itself without waiting for a repaint() call. This causes the tree to flash. I have tried setting setDoubleBuffered(true) for the nodes, the tree, and the containers it is in, but nothing changes.

Here's my code: (The class 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;
        }
    }

}
wattostudios
  • 8,666
  • 13
  • 43
  • 57
akashnil
  • 253
  • 2
  • 10
  • Are you [*mixing heavy and light components*](http://java.sun.com/products/jfc/tsc/articles/mixing/)? – trashgod Jun 16 '12 at 00:20
  • Maybe. but I don't care about performance a lot, because the overall rate of update is small enough. I just want to get rid of the flash/blinking when reloading happens. A buffer should do this. But I don't know how to do it in a simple way. – akashnil Jun 16 '12 at 00:25
  • 1
    There is no need to call `reload()` after `insertNodeInto`. `insertNodeInto` internally calls `fireTreeNodesInserted` which in turn updates the tree. – tenorsax Jun 17 '12 at 00:27

3 Answers3

2

I suspect that mixing heavy and light components is causing the flashing. The effect can be seen in this example by clicking on the circle or resizing the enclosing frame. For better guidance, please edit your question to include an sscce that exhibits the problem you describe.

Community
  • 1
  • 1
trashgod
  • 203,806
  • 29
  • 246
  • 1,045
  • Thanks for the suggestion for sscce. I'd have done it. But it seems too much work, since the problem is solved for now. – akashnil Jun 22 '12 at 00:43
0

I fixed it. I just changed

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

to

parent.add(file);

I don't know why it works now. But it does. Any comments are appreciated!

akashnil
  • 253
  • 2
  • 10
  • parent.add(file) breaks model-based update logic - you add new components only into view and need manually update UI. – adray Jul 19 '13 at 09:34
0

I've got the same trouble with custom renderer.

Just make updates inside SwingUtilities.invokeLater

SwingUtilities.invokeLater(new Runnable() {
        @Override
        public void run() {
            myTreeModel.insertNodeInto(file, parent, parent.getChildCount());
        }
adray
  • 1,408
  • 16
  • 20