【问题标题】:JTree cell renderer issueJTree 单元格渲染器问题
【发布时间】:2013-10-19 17:09:44
【问题描述】:

我有一个 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;
   }
}

提前致谢。

【问题讨论】:

  • 这是特定于 JXTree(与普通 JTree 相比)吗?无论如何,请出示一个证明问题的 SSCCE :-)
  • 不,问题不是 JXTree 特有的(问题已相应更新)。已添加 SSCCE。
  • 代码违反了“S”之一:-) 请改为独立。
  • 对,我已将配置文件节点类添加到示例中。这还不够吗?

标签: java swing jtree cellrenderer


【解决方案1】:

问题在于 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);

【讨论】:

  • 我无法让这个答案在示例或实际代码中起作用。然而,它确实促使我找到了 DefaultTreeCellRenderer 中行为的原因,并从那时起开发了一个更通用的渲染器来解决我遇到的问题。我仍然会接受这个答案,因为我可以想象通过更多的工作,我可以让它在我的代码中工作。
  • hmm ... 应该按原样工作(如果我没记错的话,您使用的是 SwingX?)
  • 是的,但仍然没有脱落。我可能使用的是旧版本的 SwingX,但我怀疑可能是这样。没有图标,也没有使用树中节点的toString时无法正常工作。
  • hmm ...应该从很久以前就可以使用。究竟是什么不工作?您能否展示一个 SSCCE 来说明此代码存在的问题?
  • 如果您将答案放入示例类中,请替换行 tree.setCellRenderer(new ProfileTreeRenderer());那么你明白我的意思了。 getIcon 方法也经常传入 null。
猜你喜欢
  • 2011-11-20
  • 1970-01-01
  • 2011-11-08
  • 1970-01-01
  • 2011-10-02
  • 2021-02-15
  • 2018-10-15
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多