2014-11-03 35 views
6

JTree öğesindeki öğeleri renklendirmek istiyorum. Ancak, sadece arka plan rengini sadece etikete eklemek garip görünüyor. Özellikle birden fazla düğüm seçilirse, ortaya çıkan şekil düzensiz ve rahatsız edici olarak görünür.JTree'de renk satırı

Arka plan, ağaç öğesinin tüm genişliğini tüm satırın renklendirilmesini sağlayacak şekilde genişletmenin bir yolu var mı? Sol sınırda başlayarak veya etiketin başında başlayarak, ancak kesinlikle bileşenin sağ kenarına kadar uzanan?

this question'a dayanan, küçük bir müstakil demo.

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 Bu kod şu anda oluşturur şeydir. Bu
Background starting at left border veya bunu tercih ederim.

+0

Ne super.getTreeCellRendererComponent (döndürdüğü bileşen için setPreferredSize() ararsanız) için Bütün sırayı kaplayacak kadar genişlik var mı? – StanislavL

+1

@StanislavL: Bu, çeşitli yerlerde otomatik boyut hesaplamayı bozar. 'GetPreferredSize' komutunu geçersiz kılmak, yüksekliğin her zamanki gibi hesaplandığından emin olur. Yine de tüm ağacın genişliğini hesaplamak imkansız olacak. Yine de, ilginç bir yaklaşım, kullanıcıların bu konuda oy kullanabilmeleri için bir cevaba değer olabilir. – MvG

+0

Kesinlikle geçersiz olan getPreferredSize() yüksekliğini korumak için daha iyidir. Ayrıca, varsayılan JTree genişlik hesaplamasını sağlam tutmak için JTree genişliğinden daha küçükse, genişliği artırmak için akıllı bir yaklaşım olabilir. – StanislavL

cevap

6

doğrudan seçim dikdörtgenler boyamak için JTree arasında paintComponent(Graphics) yöntemini geçersiz kılmak mümkün olabilir:

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 ve örnek – StanislavL

+0

Sanırım performans uğruna grafik bağlamının klip sınırlarını hesaba katmaya çalışacağım, ama bu sadece detaylar. Bunun dışında, bu benim için oldukça iyi çalışıyor. Teşekkürler! – MvG

+1

Bir sorunum var ama JXtreeTable ile bu çözümü benim nesnelere uygulamak mümkün mü? – bircastri