java - JTree 作为 JComboBox 元素不会显示 JTree
问题描述
我试图将一些 JTrees 放入一个 JCombobox 中,以下不起作用:
import javax.swing.*;
import javax.swing.tree.DefaultMutableTreeNode;
public class TestDialog extends JDialog {
public TestDialog(){
super();
JComboBox<JTree> cb = new JComboBox<>();
DefaultMutableTreeNode firstRoot = new DefaultMutableTreeNode("First Root Node");
DefaultMutableTreeNode firstChild = new DefaultMutableTreeNode("First Child Node");
DefaultMutableTreeNode secondChild = new DefaultMutableTreeNode("Second Child Node");
firstRoot.add(firstChild);
firstRoot.add(secondChild);
JTree firstTree = new JTree(firstRoot);
cb.addItem(firstTree);
DefaultMutableTreeNode secondRoot = new DefaultMutableTreeNode("Second Root Node");
DefaultMutableTreeNode childOfSecondNode = new DefaultMutableTreeNode("Child of Second Node");
secondRoot.add(childOfSecondNode);
JTree secondTree = new JTree(secondRoot);
cb.addItem(secondTree);
add(cb);
pack();
setVisible(true);
}
}
对话框不会将实际的 JTree 显示为 JCombobox 的可选元素,而是显示两个长字符串,例如javax.swing.JTree[,0,0,0x0,invalid,...]
. 我的问题是,我该如何解决这个问题?
解决方案
除了将 a 添加JTree
到 a之外JComboBox
,您还可以添加 aDefaultMutableTreeNode
并使用TreeCellRenderer
来绘制 的单元格JComboBox
。
import java.awt.*;
import java.util.Arrays;
import java.util.Collections;
import java.util.Enumeration;
import java.util.Objects;
import java.util.stream.Collectors;
import javax.swing.*;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.DefaultTreeModel;
import javax.swing.tree.TreeCellRenderer;
import javax.swing.tree.TreeModel;
public final class MainPanel {
private Component makeUI() {
DefaultMutableTreeNode firstRoot = new DefaultMutableTreeNode("First Root Node");
DefaultMutableTreeNode firstChild = new DefaultMutableTreeNode("First Child Node");
DefaultMutableTreeNode secondChild = new DefaultMutableTreeNode("Second Child Node");
firstRoot.add(firstChild);
firstRoot.add(secondChild);
DefaultMutableTreeNode secondRoot = new DefaultMutableTreeNode("Second Root Node");
DefaultMutableTreeNode childOfSecondNode = new DefaultMutableTreeNode("Child of Second Node");
secondRoot.add(childOfSecondNode);
DefaultMutableTreeNode hiddenRoot = new DefaultMutableTreeNode("Root");
hiddenRoot.add(firstRoot);
hiddenRoot.add(secondRoot);
JPanel p = new JPanel(new BorderLayout());
p.add(new TreeComboBox(new DefaultTreeModel(hiddenRoot)), BorderLayout.NORTH);
p.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
return p;
}
public static void main(String[] args) {
EventQueue.invokeLater(() -> {
JFrame f = new JFrame();
f.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
f.getContentPane().add(new MainPanel().makeUI());
f.setSize(320, 240);
f.setLocationRelativeTo(null);
f.setVisible(true);
});
}
}
class TreeComboBox extends JComboBox<DefaultMutableTreeNode> {
public TreeComboBox(TreeModel model) {
super();
DefaultMutableTreeNode root = (DefaultMutableTreeNode) model.getRoot();
DefaultComboBoxModel<DefaultMutableTreeNode> m = new DefaultComboBoxModel<>();
Collections.list((Enumeration<?>) root.preorderEnumeration()).stream()
.filter(DefaultMutableTreeNode.class::isInstance)
.map(DefaultMutableTreeNode.class::cast)
.filter(n -> !n.isRoot())
.forEach(m::addElement);
setModel(m);
}
@Override
public void updateUI() {
super.updateUI();
JTree dummyTree = new JTree();
TreeCellRenderer renderer = dummyTree.getCellRenderer();
ListCellRenderer<? super DefaultMutableTreeNode> r = getRenderer();
setRenderer((list, value, index, isSelected, cellHasFocus) -> {
Component c = r.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus);
if (value == null) {
return c;
}
if (index < 0) {
String txt = Arrays.stream(value.getPath())
.filter(DefaultMutableTreeNode.class::isInstance)
.map(DefaultMutableTreeNode.class::cast)
.filter(n -> !n.isRoot())
.map(Objects::toString)
.collect(Collectors.joining(" / "));
((JLabel) c).setText(txt);
return c;
} else {
boolean leaf = value.isLeaf();
JLabel l = (JLabel) renderer.getTreeCellRendererComponent(
dummyTree, value, isSelected, true, leaf, index, false);
int indent = Math.max(0, value.getLevel() - 1) * 16;
l.setBorder(BorderFactory.createEmptyBorder(1, indent + 1, 1, 1));
return l;
}
});
}
}
推荐阅读
- php - 单元测试应该有多详细和具体?
- powerbi - Power BI DAX - 评估正确的成本值
- php - 在数据库表 Laravel 中存储多个复选框值
- c++ - (C++)不应该这个 dynamic_cast 检索派生类
- javascript - 在应用程序中包含 Polyfill 包
- c# - 为什么我需要一个“虚拟”代码行才能加载 PresentationFramework?
- python - Scipy LDL分解返回意外结果
- c++ - 在 Eclipse 中调试 C/C++ 代码时如何查看全局变量?
- cmake - cmake 构建期间出错:CXX 编译器必须支持 Cilk
- laravel - Laravel - 最小日期和最大日期无法更新