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 に答える