2

我在树中的一些节点上有一个带有图标的 JTree。它们出现并且工作正常,但是当我选择一个带有图标的节点时,渲染器不会渲染整个选定的节点,但似乎应用了一个偏移量,就好像它认为图标仍然在节点的左侧,如下所示:

渲染错误示例

渲染器(扩展 DefaultTreeCellRenderer)的代码如下:

public ProfileTreeRenderer() {
    super.setLeafIcon(null);
    super.setClosedIcon(null);
    super.setOpenIcon(null);
}

@Override
public Component getTreeCellRendererComponent(JTree tree, Object value, boolean sel, boolean expanded, boolean leaf, int row, boolean hasFocus) {
    Component c = super.getTreeCellRendererComponent(tree, value, sel, expanded, leaf, row, hasFocus);
    if (c instanceof JLabel) {
        JLabel label = (JLabel) c;
        label.setHorizontalTextPosition(SwingConstants.LEADING);
    }

    if(sel && !hasFocus) {
        setBackgroundSelectionColor(UIManager.getColor("Panel.background"));
        setTextSelectionColor(UIManager.getColor("Panel.foreground"));
    } else {
        setTextSelectionColor(UIManager.getColor("Tree.selectionForeground"));
        setBackgroundSelectionColor(UIManager.getColor("Tree.selectionBackground"));
    } 

    if (value instanceof ProfileNode) {
        ProfileNode node = (ProfileNode) value;
        if (node.isUsed() && !sel) {
            c.setForeground(Color.GRAY);
        }

        if (node.getIcon() != null) {
            setIcon(node.getIcon());
        }
    }
}

我看不出为什么渲染器会应用这个偏移量,所以任何人都可以提供一种方法来使用图标完全选择节点吗?树本身的 SSCCE 代码如下。

public class Example extends JDialog {
    public Example() {
        JTree tree = new JTree(createModel());
        tree.setCellRenderer(new ProfileTreeRenderer());

       setLayout(new BorderLayout());
       add(tree, BorderLayout.CENTER);
    }

    private TreeModel createModel() {
        ProfileNode root = new ProfileNode("Profiles");

        ProfileNode userA = new ProfileNode("Example User A");
        ProfileNode userB = new ProfileNode("Example User B");

        // You'll need to subsitute your own 16x16 icons here
        userA.setIcon(ImageSet.USER_ICON);
        userB.setIcon(ImageSet.USER_ICON);

        root.add(userA);
        root.add(userB);

        return new DefaultTreeModel(root);
    }

    public static void main(String[] args) {
       EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                new Example().setVisible(true);
            }
        });
    }
}

ProfileNode 类:

public class ProfileNode extends DefaultMutableTreeNode {

   @Getter private String labelDisplay;
   @Getter @Setter private ImageIcon icon;

   @Getter @Setter private boolean isUsed = false;

   public ProfileNode(String labelDisplay) {
       this.labelDisplay = labelDisplay;
   }

   @Override
   public String toString() {
      return labelDisplay;
   }
}

提前致谢。

4

1 回答 1

2

问题是 DefaultTreeCellRenderer 将其图标属性专门用于打开/叶子/关闭图标:它假定 - 如果图标!= null - 它位于组件的开头(即使它不是)并调整选择因此。您需要重新调整...或使用 SwingX 渲染器 :-)

就像是:

JXTree tree = new JXTree();
tree.expandAll();
IconValue iv = new IconValue() {

    Icon icon = XTestUtils.loadDefaultIcon("green-orb.png");
    @Override
    public Icon getIcon(Object value) {
        return value.toString().contains("s") ? icon : null;
    }

};
StringValue converter = new MappedValue(StringValues.TO_STRING, iv);
WrappingProvider provider = new WrappingProvider(IconValues.NONE, converter);
// hacking around missing api ...
LabelProvider wrappee = (LabelProvider) provider.getWrappee();
wrappee.getRendererComponent(null).setHorizontalTextPosition(JLabel.LEADING);
TreeCellRenderer r = new DefaultTreeRenderer(provider);
tree.setCellRenderer(r);
于 2013-10-14T09:10:35.713 回答