Question

Using the new version of the substance look and feel for Java, the connecting lines in a typical JTree are not drawn (parent - child lines).

In the official forum in java.net someone asked the same thing and the answer of the developer for this is that it was a choice based on the newer UI's and there is no plan to implement the option in the future.

His answer also said that you could implement this yourself by subclassing the SubstanceUI class and implementing the paintHorizontalPartOfLeg / paintVerticalPartOfLeg methods.

Can someone either explain the process needed or maybe give me an example? I'm sure that someone must have done this since it is a very weird choice on behalf of the developer not to draw these lines.

Was it helpful?

Solution

This is all going from memory. I will edit if I find anything wrong with this tomorrow.

check out BasicTreeUI or MetalTreeUI. I believe they both paint lines.

What you need to do is create a new class that extends (I'm guessing on the name here) SubstanceTreeUI and override paintHorizontalPartOfLeg() and paintVerticalPartOfLeg(). Then you have a choice:

  1. You can call myTree.setUI( new MyTreeUI() )
  2. UIManager.getDefaults().put("TreeUI", MyTreeUI.class.getName() ) at some point before you make your JTree

If you don't want to subclass, try UIManager.getDefaults().put("TreeUI", BasicTreeUI.class.getName() ) and see if that looks ok.

EDIT 2: After further review it would be easier to just call .setUI(new BasicTreeUI()) on your JTree or call UIManager.getDefaults().put("TreeUI", BasicTreeUI.class.getName() ) before creating your tree.

EDIT:
SubstanceTreeUI is a cubclass of BasicTreeUI. It has overridden paintXXXPartOfLeg().

Horiz:

@Override
protected void paintHorizontalPartOfLeg(Graphics g, Rectangle clipBounds,
        Insets insets, Rectangle bounds, TreePath path, int row,
        boolean isExpanded, boolean hasBeenExpanded, boolean isLeaf) {
    boolean toPaint = (!this.tree.isEnabled())
            || this.isInside
            || !FadeConfigurationManager.getInstance().fadeAllowed(
                    SubstanceLookAndFeel.TREE_DECORATIONS_ANIMATION_KIND,
                    tree);
    if (FadeTracker.getInstance().isTracked(this.tree, SubstanceLookAndFeel.TREE_DECORATIONS_ANIMATION_KIND)) {
        Graphics2D graphics = (Graphics2D) g.create();
        graphics.setComposite(TransitionLayout
                .getAlphaComposite(this.tree,
                        FadeTracker.getInstance()
                            .getFade10(this.tree,SubstanceLookAndFeel.TREE_DECORATIONS_ANIMATION_KIND) / 10.0f,
                            g));
        super.paintHorizontalPartOfLeg(graphics, clipBounds, insets,
                bounds, path, row, isExpanded, hasBeenExpanded, isLeaf);
        graphics.dispose();
    } else if (toPaint) {
        super.paintHorizontalPartOfLeg(g, clipBounds, insets, bounds, path,
                row, isExpanded, hasBeenExpanded, isLeaf);
    }
}

It looks like the lines are only painted if either of the following is true:

  • The Tree is not enabled, the mouse is in the tree bounds [this.inside] and fading (?) is not allowed on the tree [!FadeConfigurationManager.getInstance().fadeAllowed(...)]
  • The FadeTracker is tracking the JTree [FadeTracker.getInstance().isTracked(...)]

Figure out how to ensure that the JTree is being Tracked by the FadeTracker or try this VERY rough hack (see below):

You could also cut and paste the code from BasicTreeUI's paintXXXPartOfLeg methods into a subclass.

public MyTree extends JTree {
    private boolean overrideIsEnable = false;
    public void setOverrideIsEnable(boolean b) { overrideIsEnabeld=true; }
    public boolean isOverrideIsEnable(boolean b) { return overrideIsEnabeld; }
    public boolean isEnabled() {
        if(overrideIsEnabled) return false;
        return super.isEnabled();
    }
}


class MyTreeUI extends SubstanceTreeUI {
protected void paintHorizontalPartOfLeg(Graphics g, Rectangle clipBounds,
        Insets insets, Rectangle bounds, TreePath path, int row,
        boolean isExpanded, boolean hasBeenExpanded, boolean isLeaf) {
if(this.tree instanceof MyTree)
try {
   Field f = SubstanceTreeUI.class.getDeclaredField("inside");
   f.setAccessible(true);
   Boolean v = (Boolean)f.get(this);
   f.set(this,Boolean.true);
   ((MyTree)this.tree).setOverrideIsEnable(true);
} catch(Throwable t) {
   //want to default back to substanceUI if this fails.
}
super.paintHoriz.....();
try{
    f.set(this,v);
    ((MyTree)this.tree).setOverrideIsEnable(true);
}catch(Throwable t) {
   //see above
}
}
//repeat for Vertical
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top