首先,你真的不需要扩展JTree
,您没有向该类添加任何新功能(也没有实际使用它),而是只是创建一个实例JTree
并传递一个实例 aTreeModel
它对您的数据进行建模。
这意味着您可以自由添加TreeListSelection
to the JTree
,它会告诉您选择何时发生变化。从结果来看TreeSelectionEvent
你可以获得所选的path
,它将告诉您从根到当前选定的节点选择的组件。然后您可以使用getLastPathComponent
获取路径中的最后一个节点(这将是选定的节点)。
获得此信息后,您就可以决定如何最好地将其提供给相应的视图。因为你正在使用DefaultMutableTreeNode
,您可以关联一个userObject
有了它,就可以更轻松地在每个节点上存储复杂的数据。
根据您的Viewer
类,看起来数据非常通用,在这种情况下,我会考虑创建 POJO 来维护所有关联的数据,并将其简单地应用到DefaultMutableTreeNode
,这样你就可以使用getUserObject
轻松提取它。然后您只需将此对象传递给Viewer
面板(通过某种设置器)并让查看器相应地更新其自己的状态
看一下如何使用树木 http://docs.oracle.com/javase/tutorial/uiswing/components/tree.html更多细节
例如...
import java.awt.BorderLayout;
import java.awt.EventQueue;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.text.DateFormat;
import java.time.LocalDate;
import java.time.Month;
import java.util.Date;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextField;
import javax.swing.JTree;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
import javax.swing.event.TreeSelectionEvent;
import javax.swing.event.TreeSelectionListener;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.DefaultTreeModel;
import javax.swing.tree.TreePath;
public class InterviewBrowser {
public static void main(String[] args) {
new InterviewBrowser();
}
public InterviewBrowser() {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
ex.printStackTrace();
}
DefaultMutableTreeNode root = new DefaultMutableTreeNode("Management");
DefaultMutableTreeNode bigLeaf1 = new DefaultMutableTreeNode("Generl Affair");
DefaultMutableTreeNode bigLeaf2 = new DefaultMutableTreeNode("Personal Affair");
DefaultMutableTreeNode leaf2 = new DefaultMutableTreeNode(new InterviewHistory(
"Bob",
new Date(LocalDate.of(1972, Month.MARCH, 8).toEpochDay()),
Sex.MALE,
new Date(LocalDate.of(2015, Month.AUGUST, 10).toEpochDay()),
false,
"123456789"));
DefaultMutableTreeNode leaf3 = new DefaultMutableTreeNode(new InterviewHistory(
"Jane",
new Date(LocalDate.of(1973, Month.JANUARY, 1).toEpochDay()),
Sex.FEMALE,
new Date(LocalDate.of(2015, Month.AUGUST, 10).toEpochDay()),
true,
"87654321"));
bigLeaf1.add(leaf2);
bigLeaf2.add(leaf3);
root.add(bigLeaf1);
root.add(bigLeaf2);
DefaultTreeModel model = new DefaultTreeModel(root);
JTree tree = new JTree(model);
Viewer viewer = new Viewer();
tree.addTreeSelectionListener(new TreeSelectionListener() {
@Override
public void valueChanged(TreeSelectionEvent e) {
TreePath path = e.getPath();
Object lastPathComponent = path.getLastPathComponent();
if (lastPathComponent instanceof DefaultMutableTreeNode) {
DefaultMutableTreeNode node = (DefaultMutableTreeNode) lastPathComponent;
Object userObject = node.getUserObject();
if (userObject instanceof InterviewHistory) {
InterviewHistory history = (InterviewHistory) userObject;
viewer.setHistory(history);
} else {
viewer.setHistory(null);
}
} else {
viewer.setHistory(null);
}
}
});
JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(new JScrollPane(tree), BorderLayout.WEST);
frame.add(viewer);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public enum Sex {
MALE,
FEMALE
}
public class InterviewHistory {
private String name;
private Date birthDate;
private Sex sex;
private Date interviewDate;
private boolean passed;
private String phone;
public InterviewHistory(String name, Date birthDate, Sex sex, Date interviewDate, boolean passed, String phone) {
this.name = name;
this.birthDate = birthDate;
this.sex = sex;
this.interviewDate = interviewDate;
this.passed = passed;
this.phone = phone;
}
public String getName() {
return name;
}
public Date getBirthDate() {
return birthDate;
}
public Sex getSex() {
return sex;
}
public Date getInterviewDate() {
return interviewDate;
}
public boolean didPass() {
return passed;
}
public String getPhone() {
return phone;
}
@Override
public String toString() {
return getName();
}
}
public static class Viewer extends JPanel {
public static final DateFormat DATE_FORMAT = DateFormat.getDateInstance();
private JTextField name;
private JTextField dateOfBirth;
private JLabel sex;
private JTextField dateOfInterview;
private JCheckBox passed;
private JTextField phone;
public Viewer() {
setLayout(new GridBagLayout());
GridBagConstraints gbc = new GridBagConstraints();
gbc.gridx = 0;
gbc.gridy = 0;
gbc.anchor = GridBagConstraints.WEST;
add(new JLabel("Name: "), gbc);
gbc.gridy++;
add(new JLabel("Date of birth: "), gbc);
gbc.gridy++;
add(new JLabel("Sex: "), gbc);
gbc.gridy++;
add(new JLabel("Date of Interview: "), gbc);
gbc.gridy++;
add(new JLabel("Passed interview: "), gbc);
gbc.gridy++;
add(new JLabel("Phone: "), gbc);
name = new JTextField(25);
dateOfBirth = new JTextField(10);
sex = new JLabel("?");
dateOfInterview = new JTextField(10);
passed = new JCheckBox();
phone = new JTextField(9);
gbc.gridx++;
gbc.gridy = 0;
add(name, gbc);
gbc.gridy++;
add(dateOfBirth, gbc);
gbc.gridy++;
add(sex, gbc);
gbc.gridy++;
add(dateOfInterview, gbc);
gbc.gridy++;
add(passed, gbc);
gbc.gridy++;
add(phone, gbc);
}
public void setHistory(InterviewHistory history) {
name.setText(history == null ? null : history.getName());
dateOfBirth.setText(history == null ? null : DATE_FORMAT.format(history.getBirthDate()));
sex.setText(history == null ? "?" : history.getSex().name());
dateOfInterview.setText(history == null ? null : DATE_FORMAT.format(history.getInterviewDate()));
passed.setSelected(history == null ? false : history.didPass());
phone.setText(history == null ? "?" : history.getPhone());
}
}
}
不要依赖于以下状态static
变量,该状态很容易不反映现实,而是依赖于可以从视图/模型的状态确定的实际已知值。
任何模型的目的都是为您提供一种显示数据的机制,您应该使用它直接包装数据,而不是尝试猜测 UI 或模型的状态,然后单独查找数据(恕我直言)