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);
});
}
}
此问题基于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);
});
}
}