2014-11-03 17 views
6

Tôi muốn tô màu các thành phần trong JTree. Tuy nhiên, chỉ cần thêm màu nền cho nhãn có vẻ lạ. Đặc biệt nếu nhiều hơn một nút được chọn, hình dạng kết quả trông rách rưới và mất tập trung.Hàng màu trong JTree

Có cách nào để làm nền mở rộng toàn bộ chiều rộng của phần tử cây, sao cho toàn bộ hàng được tô màu? Hoặc là bắt đầu từ biên giới bên trái hoặc bắt đầu ở đầu nhãn, nhưng chắc chắn mở rộng cho đến khi biên giới bên phải của thành phần?

Đây là bản trình diễn khép kín nhỏ, dựa trên this question.

import java.awt.*; 
import javax.swing.*; 
import javax.swing.tree.*; 
public class SO26724913 { 
    public static void main(String[] args) { 
     DefaultMutableTreeNode a = new DefaultMutableTreeNode("a"); 
     DefaultMutableTreeNode b = new DefaultMutableTreeNode("b"); 
     DefaultMutableTreeNode c = new DefaultMutableTreeNode("c"); 
     a.add(b); 
     a.add(c); 
     final JTree tree = new JTree(a); 
     tree.setCellRenderer(new DefaultTreeCellRenderer() { 
       @Override 
       public Component getTreeCellRendererComponent 
        (JTree tree, Object value, boolean selected, 
        boolean expanded, boolean leaf, int row, boolean focus) 
       { 
        JComponent c = (JComponent) 
         super.getTreeCellRendererComponent 
         (tree, value, selected, expanded, leaf, row, focus); 
        DefaultMutableTreeNode node = (DefaultMutableTreeNode)value; 
        String data = (String)node.getUserObject(); 
        if ("b".equals(data)) { 
         c.setBackground(Color.RED); 
         c.setOpaque(true); 
        } 
        else { 
         c.setBackground(null); 
         c.setOpaque(false); 
        } 
        return c; 
       } 
      }); 
     JFrame frm = new JFrame(); 
     frm.getContentPane().add(tree); 
     frm.setSize(200, 200); 
     frm.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
     frm.setVisible(true); 
    } 
} 

Current rendering Đây là mã hiện đang tạo.

Background starting at icon Tôi thích hoặc là
Background starting at left border hoặc điều này.

+0

gì nếu bạn gọi phương thức setPreferredSize() cho thành phần được trả về bởi super.getTreeCellRendererComponent() để có chiều rộng đủ lớn để bao gồm toàn bộ hàng? – StanislavL

+1

@StanislavL: Điều đó sẽ phá vỡ tính toán kích thước tự động ở một vài nơi. Thay thế 'getPreferredSize' thay vì đảm bảo chiều cao được tính như bình thường. Tuy nhiên, tính toán chiều rộng của toàn bộ cây sẽ trở thành không thể. Tuy nhiên, cách tiếp cận thú vị, có thể đáng để trả lời để người dùng có thể bỏ phiếu cho vấn đề này. – MvG

+0

Chắc chắn ghi đè getPreferredSize() là tốt hơn để giữ chiều cao. Nó cũng có thể là cách tiếp cận thông minh để tăng độ rộng chỉ khi nó nhỏ hơn chiều rộng JTree để giữ nguyên tính toán chiều rộng JTree mặc định. – StanislavL

Trả lời

6

Bạn có thể có thể ghi đè lên các phương pháp paintComponent(Graphics) của JTree để vẽ hình chữ nhật lựa chọn trực tiếp:

enter image description here

import java.awt.*; 
import java.awt.event.*; 
import java.util.Arrays; 
import javax.swing.*; 
import javax.swing.tree.*; 

public class ColorTreeTest { 
    private static final Color SELC = Color.RED; 
    public JComponent makeUI() { 
    FocusListener fl = new FocusListener() { 
     @Override public void focusGained(FocusEvent e) { 
     e.getComponent().repaint(); 
     } 
     @Override public void focusLost(FocusEvent e) { 
     e.getComponent().repaint(); 
     } 
    }; 
    DefaultTreeCellRenderer r = new DefaultTreeCellRenderer() { 
     @Override public Component getTreeCellRendererComponent(
      JTree tree, Object value, boolean selected, boolean expanded, 
      boolean leaf, int row, boolean hasFocus) { 
     JLabel l = (JLabel) super.getTreeCellRendererComponent(
      tree, value, selected, expanded, leaf, row, false); 
     l.setBackground(selected ? Color.RED 
           : tree.getBackground()); 
     l.setOpaque(true); 
     return l; 
     } 
    }; 
    JPanel p = new JPanel(new GridLayout(1, 2)); 
    for (JTree t : Arrays.asList(new ColorTree1(), new ColorTree2())) { 
     t.addFocusListener(fl); 
     t.setCellRenderer(r); 
     t.setOpaque(false); 
     p.add(new JScrollPane(t)); 
    } 
    return p; 
    } 
    static class ColorTree1 extends JTree { 
    @Override public void paintComponent(Graphics g) { 
     g.setColor(getBackground()); 
     g.fillRect(0, 0, getWidth(), getHeight()); 
     if (getSelectionCount() > 0) { 
     g.setColor(SELC); 
     for (int i : getSelectionRows()) { 
      Rectangle r = getRowBounds(i); 
      g.fillRect(r.x, r.y, getWidth() - r.x, r.height); 
     } 
     } 
     super.paintComponent(g); 
     if (getLeadSelectionPath() != null) { 
     Rectangle r = getRowBounds(getRowForPath(getLeadSelectionPath())); 
     g.setColor(hasFocus() ? SELC.darker() : SELC); 
     g.drawRect(r.x, r.y, getWidth() - r.x - 1, r.height - 1); 
     } 
    } 
    } 
    static class ColorTree2 extends JTree { 
    private static final Color SELC = Color.RED; 
    @Override public void paintComponent(Graphics g) { 
     g.setColor(getBackground()); 
     g.fillRect(0, 0, getWidth(), getHeight()); 
     if (getSelectionCount() > 0) { 
     g.setColor(SELC); 
     //@see http://ateraimemo.com/Swing/TreeRowSelection.html 
     for (int i : getSelectionRows()) { 
      Rectangle r = getRowBounds(i); 
      g.fillRect(0, r.y, getWidth(), r.height); 
     } 
     } 
     super.paintComponent(g); 
     if (getLeadSelectionPath() != null) { 
     Rectangle r = getRowBounds(getRowForPath(getLeadSelectionPath())); 
     g.setColor(hasFocus() ? SELC.darker() : SELC); 
     g.drawRect(0, r.y, getWidth() - 1, r.height - 1); 
     } 
    } 
    } 
    public static void main(String... args) { 
    EventQueue.invokeLater(new Runnable() { 
     @Override public void run() { 
     createAndShowGUI(); 
     } 
    }); 
    } 
    public static void createAndShowGUI() { 
    JFrame f = new JFrame(); 
    f.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE); 
    f.getContentPane().add(new ColorTreeTest().makeUI()); 
    f.setSize(320, 240); 
    f.setLocationRelativeTo(null); 
    f.setVisible(true); 
    } 
} 
+0

+1 cho cách tiếp cận đơn giản và ví dụ – StanislavL

+0

Tôi đoán rằng vì lợi ích của hiệu suất tôi sẽ cố gắng để có những giới hạn clip của bối cảnh đồ họa vào tài khoản, nhưng đó chỉ là chi tiết. Ngoài ra, điều này hoạt động khá tốt đối với tôi. Cảm ơn! – MvG

+1

Tôi có một số vấn đề nhưng với JXtreeTable, nó là possibile để áp dụng giải pháp này tại đối tượng của tôi? – bircastri