简介
Oracle 有一个有用的教程,Creating a GUI With Swing。跳过“使用 NetBeans IDE 学习”部分。
您正在尝试用一种方法完成所有工作。将您的代码分解为简单的方法和类。一个方法应该做一件事,并且代码不超过 20 行。这样,您无需滚动即可在屏幕上看到整个方法。
说明
当我创建 Swing GUI 时,我使用 model–view–controller (MVC) 模式。这种模式使我能够分离我的关注点并一次专注于 Swing 应用程序的一个部分。
这是我用来测试代码的简单 GUI 的图像。
型号
我创建了两个模型类。 Category 类包含与 MySQL 数据库表的一行相同的信息。
public class Category {
private final int id;
private final Integer parentId;
private final BufferedImage icon;
private final String description, name;
public Category(int id, String name, String description, Integer parentId,
BufferedImage icon) {
this.id = id;
this.name = name;
this.description = description;
this.parentId = parentId;
this.icon = icon;
}
public int getId() {
return id;
}
public Integer getParentId() {
return parentId;
}
public BufferedImage getIcon() {
return icon;
}
public String getDescription() {
return description;
}
public String getName() {
return name;
}
@Override
public String toString() {
return getName();
}
}
JTreeModel 类构造了JTree 模型。这是迭代代码。对于每个级别,您都需要在 createTreeModel 方法中添加一个 for 循环来查找叶子。
createTreeModelmethod 应该是递归方法,但我无法编写代码使其递归。如果其他人可以创建递归方法,那将是一个很好的例子。查看代码,您可以了解为什么人们建议使用 MySQL 递归。
public class JTreeModel {
private final DefaultMutableTreeNode rootNode;
public JTreeModel() {
List<Category> categoryList = readSQLTable();
this.rootNode = createTreeModel(categoryList);
}
private List<Category> readSQLTable() {
//
// Here's where you read the MySQL table into a List.
// I'd create a separate SQL class to handle all SQL.
//
// I'm just going to hard code the information for the example
//
List<Category> categoryList = new ArrayList<>();
categoryList.add(new Category(1, "Juice & Water", null, 0, null));
categoryList.add(new Category(2, "Tools", null, 0, null));
categoryList.add(new Category(3, "Cleaning Supp.", null, 0, null));
categoryList.add(new Category(4, "Snack", null, 0, null));
categoryList.add(new Category(5, "Cosmetics", null, 0, null));
categoryList.add(new Category(0, "CATEGORIES", null, null, null));
categoryList.add(new Category(6, "Shampoo", null, 5, null));
categoryList.add(new Category(7, "Water", null, 1, null));
return categoryList;
}
private DefaultMutableTreeNode createTreeModel(
List<Category> categoryList) {
DefaultMutableTreeNode rootNode =
new DefaultMutableTreeNode("Accounts Tree");
// First, find the root
Category rootCategory = getRoot(categoryList);
DefaultMutableTreeNode categoryNode =
new DefaultMutableTreeNode(rootCategory);
rootNode.add(categoryNode);
// Next, find the leaves;
List<DefaultMutableTreeNode> leafNodes = addLeaves(
categoryList, categoryNode);
for (DefaultMutableTreeNode leafNode : leafNodes) {
addLeaves(categoryList, leafNode);
}
return rootNode;
}
private List<DefaultMutableTreeNode> addLeaves(List<Category> categoryList,
DefaultMutableTreeNode rootNode) {
List<DefaultMutableTreeNode> nodeList = new ArrayList<>();
Category rootCategory = (Category) rootNode.getUserObject();
int rootId = rootCategory.getId();
List<Category> leafList = getLeaves(categoryList, rootId);
for (Category category : leafList) {
DefaultMutableTreeNode node = new DefaultMutableTreeNode(category);
nodeList.add(node);
rootNode.add(node);
}
return nodeList;
}
private Category getRoot(List<Category> categoryList) {
Category rootCategory = null;
for (Category category : categoryList) {
if (category.getParentId() == null) {
rootCategory = category;
break;
}
}
return rootCategory;
}
private List<Category> getLeaves(List<Category> categoryList, int parentId) {
List<Category> leafList = new ArrayList<>();
for (Category category : categoryList) {
Integer testParentId = category.getParentId();
if (testParentId != null && testParentId == parentId) {
leafList.add(category);
}
}
return leafList;
}
public DefaultMutableTreeNode getRootNode() {
return rootNode;
}
}
代码
这是完整的可运行代码。我将所有额外的类都设为内部类,这样我就可以将代码作为一个块发布。
import java.awt.BorderLayout;
import java.awt.image.BufferedImage;
import java.util.ArrayList;
import java.util.List;
import javax.swing.BorderFactory;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTree;
import javax.swing.SwingUtilities;
import javax.swing.tree.DefaultMutableTreeNode;
public class JTreeExample implements Runnable {
public static void main(String[] args) {
SwingUtilities.invokeLater(new JTreeExample());
}
private final JTreeModel model;
public JTreeExample() {
this.model = new JTreeModel();
}
@Override
public void run() {
JFrame frame = new JFrame("JTree Example");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(createMainPanel(), BorderLayout.CENTER);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
private JPanel createMainPanel() {
JPanel panel = new JPanel(new BorderLayout());
panel.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
JTree tree = new JTree(model.getRootNode());
for (int index = 0; index < tree.getRowCount(); index++) {
tree.expandRow(index);
}
JScrollPane scrollPane = new JScrollPane(tree);
panel.add(scrollPane, BorderLayout.CENTER);
return panel;
}
public class JTreeModel {
private final DefaultMutableTreeNode rootNode;
public JTreeModel() {
List<Category> categoryList = readSQLTable();
this.rootNode = createTreeModel(categoryList);
}
private List<Category> readSQLTable() {
//
// Here's where you read the MySQL table into a List.
// I'd create a separate SQL class to handle all SQL.
//
// I'm just going to hard code the information for the example
//
List<Category> categoryList = new ArrayList<>();
categoryList.add(new Category(1, "Juice & Water", null, 0, null));
categoryList.add(new Category(2, "Tools", null, 0, null));
categoryList.add(new Category(3, "Cleaning Supp.", null, 0, null));
categoryList.add(new Category(4, "Snack", null, 0, null));
categoryList.add(new Category(5, "Cosmetics", null, 0, null));
categoryList.add(new Category(0, "CATEGORIES", null, null, null));
categoryList.add(new Category(6, "Shampoo", null, 5, null));
categoryList.add(new Category(7, "Water", null, 1, null));
return categoryList;
}
private DefaultMutableTreeNode createTreeModel(
List<Category> categoryList) {
DefaultMutableTreeNode rootNode =
new DefaultMutableTreeNode("Accounts Tree");
// First, find the root
Category rootCategory = getRoot(categoryList);
DefaultMutableTreeNode categoryNode =
new DefaultMutableTreeNode(rootCategory);
rootNode.add(categoryNode);
// Next, find the leaves;
List<DefaultMutableTreeNode> leafNodes = addLeaves(
categoryList, categoryNode);
for (DefaultMutableTreeNode leafNode : leafNodes) {
addLeaves(categoryList, leafNode);
}
return rootNode;
}
private List<DefaultMutableTreeNode> addLeaves(List<Category> categoryList,
DefaultMutableTreeNode rootNode) {
List<DefaultMutableTreeNode> nodeList = new ArrayList<>();
Category rootCategory = (Category) rootNode.getUserObject();
int rootId = rootCategory.getId();
List<Category> leafList = getLeaves(categoryList, rootId);
for (Category category : leafList) {
DefaultMutableTreeNode node = new DefaultMutableTreeNode(category);
nodeList.add(node);
rootNode.add(node);
}
return nodeList;
}
private Category getRoot(List<Category> categoryList) {
Category rootCategory = null;
for (Category category : categoryList) {
if (category.getParentId() == null) {
rootCategory = category;
break;
}
}
return rootCategory;
}
private List<Category> getLeaves(List<Category> categoryList, int parentId) {
List<Category> leafList = new ArrayList<>();
for (Category category : categoryList) {
Integer testParentId = category.getParentId();
// System.out.println(parentId + " " + testParentId);
if (testParentId != null && testParentId == parentId) {
leafList.add(category);
}
}
return leafList;
}
public DefaultMutableTreeNode getRootNode() {
return rootNode;
}
}
public class Category {
private final int id;
private final Integer parentId;
private final BufferedImage icon;
private final String description, name;
public Category(int id, String name, String description, Integer parentId,
BufferedImage icon) {
this.id = id;
this.name = name;
this.description = description;
this.parentId = parentId;
this.icon = icon;
}
public int getId() {
return id;
}
public Integer getParentId() {
return parentId;
}
public BufferedImage getIcon() {
return icon;
}
public String getDescription() {
return description;
}
public String getName() {
return name;
}
@Override
public String toString() {
return getName();
}
}
}