JTree 中的颜色行

Color rows in JTree

此问题基于this question

我希望树的颜色根据节点所在的层而不同。 当我使用标准 groundNonSelectionColor

时,这项工作很好

this is how it Looks right now

我希望这种颜色覆盖 JScrollPanel 的整个宽度。

示例代码:

import java.awt.BorderLayout;

import java.awt.Color;

import java.awt.Component;

import java.awt.Dimension;

import java.awt.Rectangle;


import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTree;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.DefaultTreeCellRenderer;

public class Main extends JFrame {


public Main(){

    JFrame f = new JFrame();



    JTree tree = new JTree();

     MyTreeCellRenderer renderer = new MyTreeCellRenderer();

 tree.setCellRenderer(renderer);

    JScrollPane p = new JScrollPane(tree);


    f.getContentPane().add(BorderLayout.CENTER,p);
    f.setVisible(true);
    f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    f.setSize(400,400);

}


public static void main(String[] args) {
    new Main();
}
public static class MyTreeCellRenderer extends DefaultTreeCellRenderer{

    public Component getTreeCellRendererComponent(JTree tree,Object value,boolean sel,
             boolean expanded,boolean leaf,int row,boolean hasFocus) {


        JComponent component  = (JComponent)super.getTreeCellRendererComponent(tree, value, sel,expanded, leaf, row,hasFocus);

        if (getRowOfNode(value) != -1 ) {

             DefaultMutableTreeNode node = (DefaultMutableTreeNode)value;   


             switch (getRowOfNode(value)){
             //Different Level - Different Colors => 1 == Root               
                case 1: component.setBackground(Color.RED);break;           
                case 2: component.setBackground(Color.BLUE);component.setForeground(Color.WHITE);break;
                case 3: component.setBackground(Color.YELLOW);break;                    
             }                   
        }

        //component.setPreferredSize(new Dimension(tree.getWidth(),tree.getRowHeight()));         

        component.setOpaque(true);

        return component;

    }
}           
        public static int getRowOfNode(Object value){
            if(value instanceof DefaultMutableTreeNode){            
                DefaultMutableTreeNode node = (DefaultMutableTreeNode)value;            
                return node.getPath().length;
            }
            return -1;
        }

}

注: 如果我添加 setPreferredSize 面板根本不显示任何内容(tree.getWidth() 工作正常) 在上面 link 的帮助下,我能够获得整行的选择背景,而不仅仅是文本,但我无法让它像那样为所有行着色。

指定上面 Questino linked 的解决方案的差异:

在问题 link 中整行我们只有在项目被选中时才会被着色。我的问题是在未选择项目时为整行着色(在 linked 问题的解决方案中问题与我的示例图片中的问题相同! - 只有在选择项目时整行才会着色- 如果没有选择 Happening the Color 将减少为 node/leaf)

的标题

这可能有效:

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

public class Main2 {
  public JComponent makeUI() {
    JTree tree = new ColorTree2();
    tree.setCellRenderer(new MyTreeCellRenderer());
    tree.setOpaque(false);
    return new JScrollPane(tree);
  }

  static class ColorTree2 extends JTree {
    @Override public void paintComponent(Graphics g) {
      Graphics2D g2 = (Graphics2D) g.create();
      g2.setColor(getBackground());
      g2.fillRect(0, 0, getWidth(), getHeight());
      for (int i = 0; i < getRowCount(); i++) {
        Object o = getPathForRow(i).getLastPathComponent();
        g2.setColor(getNodeColor(o));
        Rectangle r = getRowBounds(i);
        g2.fillRect(0, r.y, getWidth(), r.height);
      }
      g2.dispose();
      super.paintComponent(g);
    }
  }

  static class MyTreeCellRenderer extends DefaultTreeCellRenderer {
    private final Color color = new Color(0x0, true);
    @Override public Color getBackgroundSelectionColor() {
      return color;
    }
    @Override public Color getBackgroundNonSelectionColor() {
      return color;
    }
    @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, hasFocus);
      if (getRowOfNode(value) == 2) {
        l.setForeground(Color.WHITE);
      }
      return l;
    }
  }

  public static Color getNodeColor(Object value) {
    switch (getRowOfNode(value)) {
    case 1:
      return Color.RED;
    case 2:
      return Color.BLUE;
    default:
      return Color.YELLOW;
    }
  }

  public static int getRowOfNode(Object value) {
    if (value instanceof DefaultMutableTreeNode) {
      DefaultMutableTreeNode node = (DefaultMutableTreeNode) value;
      return node.getPath().length;
    }
    return -1;
  }

  public static void main(String... args) {
    EventQueue.invokeLater(() -> {
      JFrame f = new JFrame();
      f.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
      f.getContentPane().add(new Main2().makeUI());
      f.setSize(320, 240);
      f.setLocationRelativeTo(null);
      f.setVisible(true);
    });
  }
}