简体   繁体   中英

TreeCellRenderer eating CPU

I have a simple TreeCellRenderer which extracts a JButton from the node, and outputs it to the JTree.

public class ButtonCellRenderer extends JButton implements TreeCellRenderer {

  @Override
  public Component getTreeCellRendererComponent(JTree tree, Object value, boolean     selected, boolean expanded, boolean leaf, int row, boolean hasFocus) {
    //setBackgroundNonSelectionColor(tree.getBackground());
    ProgressButton b = null;
    if ((value != null) && (value instanceof DefaultMutableTreeNode)) {
      Object userObject = ((DefaultMutableTreeNode) value).getUserObject();
      if (userObject instanceof ProgressButton) {
        b = (ProgressButton) userObject;
        return b;
      }
    }
    if (b == null) {
      System.out.println("Null!");
      DefaultTreeCellRenderer defaultRenderer = new DefaultTreeCellRenderer();
      return defaultRenderer.getTreeCellRendererComponent(tree,
              value, selected, expanded, leaf, row, hasFocus);
    } else {
      System.out.println("Returning label");
      return new JLabel(b.getToolTipText(), b.getIcon(), SwingConstants.CENTER);
    }
  }
}

I'm not sure why, but it seems to be stuck looping, and eats about 30~50% CPU. Is there any way to eliminate this? Or not have to use a renderer to output a JButton into a tree?

I've added the revised code above, but now I'm getting a problem where the buttons don't display properly (they all come out small).

You are calling super.getTreeCellRendererComponent without storing the value. If later on no renderer is created you call this method again ( if c==null... ). This is expensive for itself.

More important:

A renderer should be a component that is reused and only configured for the specific value to be shown. This is why the default implementation reuses a label and just sets the text, colors, border... That is why renderer calls are quite cheap.

You create a new JLabel every time you show a value: returnLab = new JLabel(text); . This is expensive. This method will be called for each and every cell shown on each repaint event. This is much more expensive than building a grid of components and defies the whole purpose of the renderer concept.

Please have a look into the default renderer implementation to see how to do it correctly. And have a look into the tutorial .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM