2013-10-11 63 views
2

我已經在樹中的一些節點上有一個JTree圖標。它們顯示並且工作正常,但是當我使用圖標選擇一個節點時,渲染器不會呈現選定的整個節點,但似乎會應用偏移量,就好像它認爲圖標仍然位於節點的左側,如下所示:JTree單元格渲染器問題

Example of the rendering fault

渲染器的代碼(它擴展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; 
    } 
} 

在此先感謝。

+1

這是特定於JXTree(相對於普通的JTree)?無論如何,請展示一個演示問題的SSCCE :-) – kleopatra

+0

不,問題不是JXTree特定的(問題相應更新)。 SSCCE補充說。 – Ocracoke

+0

該代碼違反了「S」之一:-)請更改爲獨立。 – kleopatra

回答

2

問題是,DefaultTreeCellRenderer專門爲open/leaf/close圖標使用它的圖標屬性:它假定 - 如果圖標!= 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); 
+0

我無法在示例或實際代碼中使此答案有效。但是,它確實提示我在DefaultTreeCellRenderer中找到行爲的原因,並且自此開發了更通用的渲染器來解決我遇到的問題。我仍然會接受這個答案,因爲我可以想象,通過更多的工作,我可以讓它在我的代碼中工作。 – Ocracoke

+0

嗯......應該按原樣工作(如果我沒有記錯的話,你正在使用SwingX?) – kleopatra

+0

是的,儘管如此,還是沒有出現。我可以使用舊版本的SwingX,但我懷疑這可能是它。當沒有圖標並且沒有在樹中使用節點的toString時,它沒有正常工作。 – Ocracoke