带有自定义项的Java Swing Jtree或Jlist

带有自定义项的Java Swing Jtree或Jlist,java,swing,jlist,jtree,Java,Swing,Jlist,Jtree,有人能给我解释一下,我如何在JavaSwing桌面应用程序中创建带有自定义项的可扩展列表?我对Swing Desktop有点陌生(通常我在Android上工作),我没有看到一些好的组件可以帮助我创建这样的列表,其中包含图像和文本。我想使用JTree,但我不确定是否可以对其进行足够的定制,以获得所需的结果 这里可以使用自定义的TreeCellRenderer、树.closedIcon和树.openIcon实现: import java.awt.*; 导入java.awt.geom.*; 导入ja

有人能给我解释一下,我如何在JavaSwing桌面应用程序中创建带有自定义项的可扩展列表?我对Swing Desktop有点陌生(通常我在Android上工作),我没有看到一些好的组件可以帮助我创建这样的列表,其中包含图像和文本。我想使用
JTree
,但我不确定是否可以对其进行足够的定制,以获得所需的结果


这里可以使用自定义的
TreeCellRenderer
树.closedIcon
树.openIcon
实现:

import java.awt.*;
导入java.awt.geom.*;
导入javax.swing.*;
导入javax.swing.plaf.*;
导入javax.swing.plaf.basic.*;
导入javax.swing.tree.*;
公共类CustomItemTreeTest{
公共JComponent makeUI(){
IconUIResource emptyIcon=新IconUIResource(新图标(){
@覆盖公共虚空绘制图标(组件c、图形g、int x、int y){}
@重写公共int getIconWidth(){
返回0;
}
@重写公共int getIconHeight(){
返回0;
}
});
UIManager.put(“Tree.expandedIcon”,emptyIcon);
UIManager.put(“树.塌陷医学”,emptyIcon);
//UIManager.put(“Tree.closedIcon”,emptyIcon);
//UIManager.put(“Tree.openIcon”,emptyIcon);
UIManager.put(“Tree.paintLines”,Boolean.FALSE);
UIDefaults d=新的UIDefaults();
d、 放置(“树:TreeCell[Enabled+Selected].backgroundPainter”,新的Painter(){
@覆盖公共空白绘制(图形2D g、J组件c、int w、int h){
g、 setPaint(Color.GREEN.darker());
g、 fillRect(0,0,w,h);
}
});
JTree-tree=新的JTree(makeModel());
setCellRenderer(新的TestTreeCellRenderer());
//树。设置行高(0);
tree.setRootVisible(false);
tree.setShowsRootHandles(假);
树。挫折地(颜色。白色);
tree.putClientProperty(“Nimbus.Overrides”,d);
tree.putClientProperty(“Nimbus.Overrides.InheritDefaults”,false);
返回新的JScrollPane(树);
}
私有静态树模型makeModel(){
维度d64=新维度(64,64);
尺寸d32=新尺寸(32,32);
尺寸d24=新尺寸(24,24);
DefaultMutableTreeNode根=新的DefaultMutableTreeNode(“根”);
DefaultMutableTreeNode set1=新的DefaultMutableTreeNode(
新的TestNode(“子类别1”,Color.ORANGE,d64,false));
set1.add(新的DefaultMutableTreeNode(
新的测试节点(“子类别1”,Color.ORANGE,d32,true));
set1.add(新的DefaultMutableTreeNode(
新的TestNode(“SubSubCategory 2”,Color.CYAN.darker(),d32,true));
set1.add(新的DefaultMutableTreeNode(
新的TestNode(“子类别3”,Color.GREEN,d32,true));
DefaultMutableTreeNode set2=新的DefaultMutableTreeNode(
新的TestNode(“子类别2”,Color.GREEN.darker().darker(),d64,false));
DefaultMutableTreeNode集合3=新的DefaultMutableTreeNode(
新的TestNode(“子类别5”,Color.GREEN,d32,false));
set3.add(新的DefaultMutableTreeNode(
新的TestNode(“subsubcategory 1”,Color.BLUE,d24,true));
set3.add(新的DefaultMutableTreeNode(
新的TestNode(“subsubcategory 2”,Color.GREEN,d24,true));
set3.add(新的DefaultMutableTreeNode(
新的TestNode(“subsubcategory 3”,Color.ORANGE.darker(),d24,true));
set2.add(新的DefaultMutableTreeNode(
新的测试节点(“子类别4”,Color.ORANGE.darker().darker(),d32,true));
set2.add(set3);
set2.add(新的DefaultMutableTreeNode(
新的TestNode(“子类别6”,Color.ORANGE,d32,true));
root.add(set1);
root.add(set2);
返回新的DefaultTreeModel(根);
}
公共静态void main(字符串…参数){
EventQueue.invokeLater(()->{
试一试{
对于(UIManager.LookAndFeelInfo-laf:UIManager.getInstalledLookAndFeels()){
if(“Nimbus”.equals(laf.getName())){
UIManager.setLookAndFeel(laf.getClassName());
}
}
}捕获(例外情况除外){
例如printStackTrace();
}
JFrame f=新的JFrame();
f、 setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
f、 getContentPane().add(新的CustomItemTreeTest().makeUI());
f、 设置大小(320512);
f、 setLocationRelativeTo(空);
f、 setVisible(真);
});
}
}
类TestTreeCellRenderer扩展了DefaultTreeCellRenderer{
@重写公共组件GetTreeCellRenderComponent(
JTree树,对象值,布尔选择,布尔扩展,
布尔叶,int行,布尔hasFocus){
JLabel=(JLabel)super.gettreecellrenderComponent(
树、值、选定、展开、叶、行、焦点);
if(DefaultMutableTreeNode的值实例){
DefaultMutableTreeNode=(DefaultMutableTreeNode)值;
Object uo=node.getUserObject();
if(测试节点的uo实例){
TestNode i=(TestNode)uo;
l、 设置前景(颜色为黑色);
l、 setIcon(新的TestNode(i.title、i.color、i.dim、leaf、expanded));
int缩进=0;
TreeNode parent=node.getParent();
while(DefaultMutableTreeNode的父实例){
DefaultMutableTreeNode pn=(DefaultMutableTreeNode)父级;
if(pn.getUserObject()TestNode实例){
TestNode pi=(TestNode)pn.getUserObject();
缩进+=pi.dim.width/2;
}
parent=pn.getParent();
}
l、 setboorder(BorderFactory.createEmptyByOrder(2,缩进,2,5));
}
}
返回l;
}
}
类TestNode实现图标{
公共最终字符串标题;
公共最终颜色;
公共最终维度;
私有最终布尔扩展;
私有最终布尔叶;
专用静态int GAP=4;
//公共测试节点(字符串标题、图像图标img、尺寸标注){
公共测试节点(字符串标题、颜色、尺寸标注、布尔叶){
这(标题、颜色、暗淡、叶子、假);
}
import java.awt.*;
import java.awt.geom.*;
import javax.swing.*;
import javax.swing.plaf.*;
import javax.swing.plaf.basic.*;
import javax.swing.tree.*;

public class CustomItemTreeTest {
  public JComponent makeUI() {
    IconUIResource emptyIcon = new IconUIResource(new Icon() {
      @Override public void paintIcon(Component c, Graphics g, int x, int y) {}
      @Override public int getIconWidth() {
        return 0;
      }
      @Override public int getIconHeight() {
        return 0;
      }
    });
    UIManager.put("Tree.expandedIcon",  emptyIcon);
    UIManager.put("Tree.collapsedIcon", emptyIcon);
    //UIManager.put("Tree.closedIcon",    emptyIcon);
    //UIManager.put("Tree.openIcon",      emptyIcon);
    UIManager.put("Tree.paintLines",    Boolean.FALSE);

    UIDefaults d = new UIDefaults();
    d.put("Tree:TreeCell[Enabled+Selected].backgroundPainter", new Painter<JComponent>() {
      @Override public void paint(Graphics2D g, JComponent c, int w, int h) {
        g.setPaint(Color.GREEN.darker());
        g.fillRect(0, 0, w, h);
      }
    });

    JTree tree = new JTree(makeModel());
    tree.setCellRenderer(new TestTreeCellRenderer());
    //tree.setRowHeight(0);
    tree.setRootVisible(false);
    tree.setShowsRootHandles(false);
    tree.setBackground(Color.WHITE);
    tree.putClientProperty("Nimbus.Overrides", d);
    tree.putClientProperty("Nimbus.Overrides.InheritDefaults", false);

    return new JScrollPane(tree);
  }

  private static TreeModel makeModel() {
    Dimension d64 = new Dimension(64, 64);
    Dimension d32 = new Dimension(32, 32);
    Dimension d24 = new Dimension(24, 24);
    DefaultMutableTreeNode root = new DefaultMutableTreeNode("Root");
    DefaultMutableTreeNode set1 = new DefaultMutableTreeNode(
        new TestNode("SubCategory 1", Color.ORANGE, d64, false));
    set1.add(new DefaultMutableTreeNode(
        new TestNode("SubSubCategory 1", Color.ORANGE, d32, true)));
    set1.add(new DefaultMutableTreeNode(
        new TestNode("SubSubCategory 2", Color.CYAN.darker(), d32, true)));
    set1.add(new DefaultMutableTreeNode(
        new TestNode("SubSubCategory 3", Color.GREEN, d32, true)));
    DefaultMutableTreeNode set2 = new DefaultMutableTreeNode(
        new TestNode("SubCategory 2", Color.GREEN.darker().darker(), d64, false));
    DefaultMutableTreeNode set3 = new DefaultMutableTreeNode(
        new TestNode("SubSubCategory 5", Color.GREEN, d32, false));
    set3.add(new DefaultMutableTreeNode(
        new TestNode("SubSubSubCategory 1", Color.BLUE, d24, true)));
    set3.add(new DefaultMutableTreeNode(
        new TestNode("SubSubSubCategory 2", Color.GREEN, d24, true)));
    set3.add(new DefaultMutableTreeNode(
        new TestNode("SubSubSubCategory 3", Color.ORANGE.darker(), d24, true)));
    set2.add(new DefaultMutableTreeNode(
        new TestNode("SubSubCategory 4", Color.ORANGE.darker().darker(), d32, true)));
    set2.add(set3);
    set2.add(new DefaultMutableTreeNode(
        new TestNode("SubSubCategory 6", Color.ORANGE, d32, true)));
    root.add(set1);
    root.add(set2);
    return new DefaultTreeModel(root);
  }

  public static void main(String... args) {
    EventQueue.invokeLater(() -> {
      try {
        for (UIManager.LookAndFeelInfo laf: UIManager.getInstalledLookAndFeels()) {
          if ("Nimbus".equals(laf.getName())) {
            UIManager.setLookAndFeel(laf.getClassName());
          }
        }
      } catch (Exception ex) {
        ex.printStackTrace();
      }
      JFrame f = new JFrame();
      f.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
      f.getContentPane().add(new CustomItemTreeTest().makeUI());
      f.setSize(320, 512);
      f.setLocationRelativeTo(null);
      f.setVisible(true);
    });
  }
}

class TestTreeCellRenderer extends 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, hasFocus);
    if (value instanceof DefaultMutableTreeNode) {
      DefaultMutableTreeNode node = (DefaultMutableTreeNode) value;
      Object uo = node.getUserObject();
      if (uo instanceof TestNode) {
        TestNode i = (TestNode) uo;
        l.setForeground(Color.BLACK);
        l.setIcon(new TestNode(i.title, i.color, i.dim, leaf, expanded));

        int indent = 0;
        TreeNode parent = node.getParent();
        while (parent instanceof DefaultMutableTreeNode) {
          DefaultMutableTreeNode pn = (DefaultMutableTreeNode) parent;
          if (pn.getUserObject() instanceof TestNode) {
            TestNode pi = (TestNode) pn.getUserObject();
            indent += pi.dim.width / 2;
          }
          parent = pn.getParent();
        }
        l.setBorder(BorderFactory.createEmptyBorder(2, indent, 2, 5));
      }
    }
    return l;
  }
}

class TestNode implements Icon {
  public final String title;
  public final Color color;
  public final Dimension dim;
  private final boolean expanded;
  private final boolean leaf;
  private static int GAP = 4;
  //public TestNode(String title, ImageIcon img, Dimension dim) {
  public TestNode(String title, Color color, Dimension dim, boolean leaf) {
    this(title, color, dim, leaf, false);
  }
  public TestNode(String title, Color color, Dimension dim,
                  boolean leaf, boolean expanded) {
    this.title = title;
    this.color = color;
    this.dim = dim;
    this.expanded = expanded;
    this.leaf = leaf;
  }
  @Override public void paintIcon(Component c, Graphics g, int x, int y) {
    g.setColor(color);
    g.fillRect(x + GAP, y + GAP, dim.width - GAP - GAP, dim.height - GAP - GAP);
    if (dim.width < 64) {
      Graphics2D g2 = (Graphics2D) g.create();
      g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
                          RenderingHints.VALUE_ANTIALIAS_ON);
      int w6 = dim.width / 12;
      int w3 = dim.width / 6;
      g2.setColor(Color.WHITE);
      g2.setStroke(new BasicStroke(w6));
      Point pt = new Point(x + dim.width / 2, y + dim.height / 2);
      Path2D path = new Path2D.Double();
      path.moveTo(pt.x - w6, pt.y - w3);
      path.lineTo(pt.x + w6, pt.y);
      path.lineTo(pt.x - w6, pt.y + w3);
      int numquadrants;
      if (leaf) {
        numquadrants = 0;
      } else if (expanded) {
        numquadrants = 3;
      } else {
        numquadrants = 1;
      }
      AffineTransform at = AffineTransform.getQuadrantRotateInstance(
          numquadrants, pt.x, pt.y);
      g2.draw(at.createTransformedShape(path));
      g2.dispose();
    }
  }
  @Override public int getIconWidth() {
    return dim.width;
  }
  @Override public int getIconHeight() {
    return dim.height;
  }
  @Override public String toString() {
    return title;
  }
}