swing树的节点外观_DefaultTreeCellRenderer
JTree默认的外观是比较单一的,它提供了如下几种改变结点外观的方式: 下面的三种方式,这里只学第一种,后面会学第二种和第三种
1、使用DefaultTreeCellRenderer直接改变节点的外观,这种方式可以改变整棵树所有节点的字体、颜色和图标 2、为JTree指定DefaultTreeCellRenderer的扩展类对象作为JTree的节点绘制器,该绘制器负责为不同节点使用不同的字体、颜色和图 3、为JTree指定一个实现TreeCellRenderer接口的节点绘制器,该绘制器可以为不同的节点自由绘制任意内容,这是最复杂但最灵活的节点绘制器
第一种方式最简单,但灵活性最差,因为它会改变整棵树所有节点的外观。在这种情况下,Jtree的所有节点依然使用相同的图标,相当于整体替换了Jtree中节点的所有默认图标。用户指定的节点图标未必就比JTree默认的图标美观 第二种方式是我们经常使用的,用来改变节点的外观
DefaultTreeCellRenderer提供了如下几个方法来修改节点的外观:
方法 | 作用 |
---|---|
setBackgroundNonSelectionColor(Color newColor) | 设置用于非选定节点的背景颜色 |
setBackgroundSelectionColor(Color newColor) | 设置节点在选中状态下的背景颜色 |
setBorderSelectionColor(Color newColor) | 设置选中状态下节点的边框颜色 |
setClosedIcon(Icon newIcon) | 设置处于折叠状态下非叶子节点的图标 |
setFont(Font font) | 设置节点文本的字体 |
setLeaflcon(Icon newIcon) | 设置叶子节点的图标 |
setOpenlcon(Icon newlcon) | 设置处于展开状态下非叶子节点的图标 |
setTextNonSelectionColor(Color newColor) | 设置绘制非选中状态下节点文本的颜色 |
setTextSelectionColor(Color newColor) | 设置绘制选中状态下节点文本的颜色 |
swing树的节点外观_DefaultTreeCellRenderer的练习
package ch30;
import javax.swing.*;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.DefaultTreeCellRenderer;
import java.awt.*;
public class a_28_0swing_树_节点外观_DefaultTreeCellRenderer {
//创建窗口
JFrame jf = new JFrame("改变所有结点外观");
//声明tree
JTree tree;
//创建若干节点
DefaultMutableTreeNode root = new DefaultMutableTreeNode("中国");
DefaultMutableTreeNode guangdong = new DefaultMutableTreeNode("广东");
DefaultMutableTreeNode guangxi = new DefaultMutableTreeNode("广西");
DefaultMutableTreeNode foshan = new DefaultMutableTreeNode("佛山");
DefaultMutableTreeNode shantou = new DefaultMutableTreeNode("汕头");
DefaultMutableTreeNode guilin = new DefaultMutableTreeNode("桂林");
DefaultMutableTreeNode nanning = new DefaultMutableTreeNode("南宁");
//组装视图
public void init() {
guangdong.add(foshan);
guangdong.add(shantou);
guangxi.add(guilin);
guangxi.add(nanning);
root.add(guangdong);
root.add(guangxi);
tree = new JTree(root);
//创建一个DefaultTreeCellRenderer对象
DefaultTreeCellRenderer renderer = new DefaultTreeCellRenderer();
//设置非选定结点的背景颜色
renderer.setBackgroundNonSelectionColor(new Color(240, 240, 240));
//设置选中结点的背景色
renderer.setBackgroundSelectionColor(new Color(170, 170, 170));
//设置选中状态下结点的边框颜色
renderer.setBorderSelectionColor(Color.BLACK);
//设置处于折叠状态下非叶子结点的图标
renderer.setClosedIcon(new ImageIcon("src\\img\\new.png"));
//设置结点文本的字体
renderer.setFont(new Font("StSong", Font.BOLD, 16));
//设置叶子结点图标
renderer.setLeafIcon(new ImageIcon("src\\img\\copy.png"));
//设置处于展开状态下非叶子结点图标跑
renderer.setOpenIcon(new ImageIcon("src\\img\\exit.png"));
//设置绘制非选中状态下结点文本颜色。三原色:红、绿、蓝
renderer.setTextNonSelectionColor(new Color(121, 59, 199));
//设置选中状态下结点的文本颜色
renderer.setTextSelectionColor(new Color(32, 220, 85));
//把上面写好的节点绘制器,设置给tree对象
tree.setCellRenderer(renderer);
tree.setShowsRootHandles(true);
tree.setRootVisible(true);
jf.add(new JScrollPane(tree));
jf.pack();
jf.setVisible(true);
jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
public static void main(String[] args) {
new a_28_0swing_树_节点外观_DefaultTreeCellRenderer().init();
}
}
swing树的节点外观_扩展DefaultTreeCellRenderer
扩展DefaultTreeCellRenderer改变结点外观
JTree默认的外观是比较单一的,它提供了如下几种改变结点外观的方式: 下面的三种方式,这里只学第二种,上面已经学了第一种
1、使用DefaultTreeCellRenderer直接改变节点的外观,这种方式可以改变整棵树所有节点的字体、颜色和图标 2、为JTree指定DefaultTreeCellRenderer的扩展类对象作为JTree的节点绘制器,该绘制器负责为不同节点使用不同的字体、颜色和图 3、为JTree指定一个实现TreeCellRenderer接口的节点绘制器,该绘制器可以为不同的节点自由绘制任意内容,这是最复杂但最灵活的节点绘制器
第一种方式最简单,但灵活性最差,因为它会改变整棵树所有节点的外观。在这种情况下,Jtree的所有节点依然使用相同的图标,相当于整体替换了Jtree中节点的所有默认图标。用户指定的节点图标未必就比JTree默认的图标美观。简单说就是我们这种方法无法给某个节点设置独立的样式 第二种方式是我们经常使用的,用来改变节点的外观
DefaultTreeCellRenderer实现类实现了TreeCellRenderer接口,该接口里只有一个用于绘制节点内容的方法:
xxxxxxxxxx
getTreeCellRendererComponent()
该方法负责绘制JTree节点。学习JList的时候,如果要绘制JList的列表项外观的内容,需要实现ListCellRenderer接口,通过重写getTreeCellRendererComponent()方法返回一个Component对象, 该对象就是JTree的节点组件。两者之间非常类似
DefaultTreeCellRenderer类继承了JLabel,实现getTreeCellRendererComponent()方法时返回this ,即返回一个特殊的JLabel对象,如果需要根据节点内容来改变节点的外观,则可以再次扩展DefaultTreeCellRenderer类,并再次重写它提供的getTreeCellRendererComponent()方法
swing树的节点外观_扩展DefaultTreeCellRenderer的练习
package ch30;
import javax.swing.*;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.DefaultTreeCellRenderer;
import java.awt.*;
//核心:自己写一个MyRenderer类,并让这个类继承DefaultTreeCellRenderer,继承之后要重写getTreeCellRendererComponent
public class a_29_0swing_树_节点外观_扩展DefaultTreeCellRenderer {
//创建窗口
JFrame jf = new JFrame("根据结点类型定义图标");
//声明tree
JTree tree;
//初始化5个图标
ImageIcon rootIcon = new ImageIcon("src\\img\\root.png");
ImageIcon databaseIcon = new ImageIcon("src\\img\\database.png");
ImageIcon tableIcon = new ImageIcon("src\\img\\table2.png");
ImageIcon columnIcon = new ImageIcon("src\\img\\column.png");
ImageIcon indexIcon = new ImageIcon("src\\img\\index.png");
//定义一个NodeData类,用于封装结点数据(即某个节点的名字和图标)
class NodeData {
//成员变量
public ImageIcon icon;
public String name;
//构造方法
public NodeData(ImageIcon icon, String name) {
this.icon = icon;
this.name = name;
}
}
//创建若干节点。new NodeData(意思是new一个对象),NodeData就是上面我们写的内部类,下面把参数传进去就可以了
DefaultMutableTreeNode root = new DefaultMutableTreeNode(new NodeData(rootIcon, "数据库导航"));
DefaultMutableTreeNode salaryDb = new DefaultMutableTreeNode(new NodeData(databaseIcon, "公司工资数据库"));
DefaultMutableTreeNode customerDb = new DefaultMutableTreeNode(new NodeData(databaseIcon, "公司客户数据库"));
DefaultMutableTreeNode employee = new DefaultMutableTreeNode(new NodeData(tableIcon, "员工表"));
DefaultMutableTreeNode attend = new DefaultMutableTreeNode(new NodeData(tableIcon, "考勤表"));
DefaultMutableTreeNode concat = new DefaultMutableTreeNode(new NodeData(tableIcon, "联系方式表"));
DefaultMutableTreeNode id = new DefaultMutableTreeNode(new NodeData(indexIcon, "员工ID"));
DefaultMutableTreeNode name = new DefaultMutableTreeNode(new NodeData(columnIcon, "姓名"));
DefaultMutableTreeNode gender = new DefaultMutableTreeNode(new NodeData(columnIcon, "性别"));
public void init() {
//组装节点
root.add(salaryDb);
root.add(customerDb);
salaryDb.add(employee);
salaryDb.add(attend);
customerDb.add(concat);
concat.add(id);
concat.add(name);
concat.add(gender);
//创建树
tree = new JTree(root);
//通过扩展DefaultTreeCellRenderer改变结点外观。给setCellRenderer设置一个节点渲染器,即new MyRenderer()
tree.setCellRenderer(new MyRenderer());
tree.setShowsRootHandles(true);
tree.setRootVisible(true);
//设置使用windows外观风格
try {
UIManager.setLookAndFeel("com.sun.java.swing.plaf.windows.WindowsLookAndFeel");
} catch (Exception e) {
e.printStackTrace();
}
//更新JTree的UI外观
SwingUtilities.updateComponentTreeUI(tree);
jf.add(new JScrollPane(tree));
jf.pack();
jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
jf.setVisible(true);
}
//自定义一个类,继承DefaultTreeCellRenderer,完成节点的绘制。下面那行的MyRenderer是一个组件类
private class MyRenderer extends DefaultTreeCellRenderer {
//获取树的渲染单元组件。下面那行的getTreeCellRendererComponent方法返回的是Component对象,我们在方法后面直接返回this即可
public Component getTreeCellRendererComponent(JTree tree, Object value, boolean sel, boolean expanded, boolean leaf, int row, boolean hasFocus) {
//获取当前节点,下面那行右边小括号的DefaultMutableTreeNode是强制转换的意思
DefaultMutableTreeNode node = (DefaultMutableTreeNode) value;
//获取到当前即将绘制的节点的名称和图标
NodeData nodeData = (NodeData) node.getUserObject();
//通过setText方法和setIcon方法完成设置
this.setText(nodeData.name);
this.setIcon(nodeData.icon);
return this;
}
}
public static void main(String[] args) {
new a_29_0swing_树_节点外观_扩展DefaultTreeCellRenderer().init();
}
}
swing树的节点外观_TreeCellRenderer接口
实现TreeCellRenderer接口改变结点外观
这种改变结点外观的方式是最灵活的,程序实现TreeCellRenderer接口时同样需要实现getTreeCellRendererComponent()方法,该方法可以返回任意类型的组件,该组件将作为JTree的结点。通过这种方式可以最大程度的改变结点的外观
swing树的节点外观_TreeCellRenderer接口的练习
xxxxxxxxxx
package ch30;
import javax.swing.*;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.TreeCellRenderer;
import java.awt.*;
//这里学习改变节点外观的第三种写法,前面学习的那两种写法是为节点添加图片和文字,这里的第三种写法就来学习为节点添加更复杂的外观
//案例:自定义类,继承JPanel类,实现TreeCellRenderer接口
public class a_30_0swing_树_节点外观_TreeCellRenderer接口 {
//创建窗口
JFrame jf = new JFrame("定制树的结点");
//声明tree
JTree tree;
//创建若干节点
DefaultMutableTreeNode friends = new DefaultMutableTreeNode("我的好友");
DefaultMutableTreeNode zhangsan = new DefaultMutableTreeNode("张三");
DefaultMutableTreeNode xiaoming = new DefaultMutableTreeNode("小明");
DefaultMutableTreeNode lisi = new DefaultMutableTreeNode("李四");
DefaultMutableTreeNode xiaohua = new DefaultMutableTreeNode("小华");
DefaultMutableTreeNode xiaohong = new DefaultMutableTreeNode("小红");
public void init() {
//组装节点
friends.add(zhangsan);
friends.add(xiaoming);
friends.add(lisi);
friends.add(xiaohua);
friends.add(xiaohong);
tree = new JTree(friends);
tree.setShowsRootHandles(true);
tree.setRootVisible(true);
//设置节点绘制器
MyRenderer renderer = new MyRenderer();
tree.setCellRenderer(renderer);
jf.add(new JScrollPane(tree));
jf.pack();
jf.setVisible(true);
jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
public static void main(String[] args) {
new a_30_0swing_树_节点外观_TreeCellRenderer接口().init();
}
//自定义类,实现TreeCellRenderer接口,绘制组件
private class MyRenderer extends JPanel implements TreeCellRenderer {
//成员变量。记录头像的图标、名字、背景色、前景色
private ImageIcon icon;
private String name;
private Color background;
private Color foreground;
public Component getTreeCellRendererComponent(JTree tree, Object value, boolean selected, boolean expanded, boolean leaf, int row, boolean hasFocus) {
//给成员变量赋值
this.icon = new ImageIcon("src\\img\\"+value.toString()+".png");
this.name = value.toString();
//根据是否获取到焦点,来改变背景色
this.background = hasFocus ? new Color(227, 227, 227) : new Color(255,255,255);
//根据是否获取到焦点,来改变前景色
this.foreground = hasFocus ? new Color(232, 37, 9) : new Color(0, 0, 0);
//返回当前JPanel作为结点
return this;
}
//设置当前JPanel组件结点的最佳大小,单位是像素
public Dimension getPreferredSize() {
return new Dimension(80, 80);
}
//重写paintComponent,来改变JPanel的外观,即绘制组件的图标、名字、背景色、前景色
protected void paintComponent(Graphics g) {
//图片的宽高
int imageWidth = icon.getImage().getWidth(null);
int imageHeight = icon.getImage().getHeight(null);
//绘制背景色
g.setColor(background);
g.fillRect(0, 0, getWidth(), getHeight());
//绘制前景色,即姓名的颜色
g.setColor(foreground);
//绘制头像的图标,参数:图标、x坐标、y坐标、null。getWidth是当前组件的宽,imageWidth是图片的宽
g.drawImage(this.icon.getImage(), getWidth() / 2 - imageWidth / 2, 10, null);
//绘制头像的姓名字体、大小,单位是px
g.setFont(new Font("StSong", Font.BOLD, 16));
//绘制头像的姓名:参数:姓名、x坐标、y坐标、null。18的由来:字的大小时16px,两边间隔各1px
g.drawString(this.name, getWidth() / 2 - this.name.length() * 18/2, imageHeight + 30);
}
}
}