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接口,该接口里只有一个用于绘制节点内容的方法:
xxxxxxxxxxgetTreeCellRendererComponent()该方法负责绘制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,继承之后要重写getTreeCellRendererComponentpublic 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接口的练习
xxxxxxxxxxpackage 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); }
}}