JTree 编辑器不设置变量
JTree Editor not setting variables
我正在尝试将 JTree
中的 Renderer
用于我正在开发的 Swing 应用程序,仅当树是叶对象并且由流组成时才使用自定义渲染器布局。带有图像的空标签,JComboBox
最后是包含字符串的标签。
最初 Renderer
通过 HazardRenderer.java
中的 getTreeCellRendererComponent()
方法传递一个字符串值,然后使用 HazardComboBox.java
中的 setText()
方法设置然后编辑器获取选定的渲染器实例并使用相同的 setText()
方法设置文本。
但是,当在 HazardEditor()
中调用 ItemListener
时,标签文本会被清除。我可以验证这一点,因为注释掉侦听器可以消除问题,但我需要一个侦听器能够告诉应用程序编辑器的编辑已经可靠地完成。这个问题的解决方案是什么?下面的代码;
Main.java
public class Main {
public JComponent makeUI() {
JTree tree = new JTree();
tree.setEditable(true);
tree.setRootVisible(false);
tree.setCellRenderer(new HazardRenderer());
tree.setCellEditor(new HazardEditor());
//tree.setModel() excluded for brevity
return new JScrollPane(tree);
}
public static void main(String[] args) {
EventQueue.invokeLater(() -> {
JFrame f = new JFrame();
f.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
f.getContentPane().add(new Main().makeUI());
f.pack();
f.setLocationRelativeTo(null);
f.setVisible(true);
});
}
}
HazardComboBox.java
public class HazardComboBox extends JPanel {
private JLabel lblLabel = new JLabel("Placeholder");
private JComboBox comboBox = new JComboBox(HazardSelection.values());
public HazardComboBox() {
setBackground(Color.WHITE);
setLayout(new FlowLayout(FlowLayout.CENTER, 0, 0));
JLabel label = new JLabel("");
label.setIcon(new ImageIcon(HazardComboBox.class.getResource("/javax/swing/plaf/metal/icons/ocean/file.gif")));
add(label);
comboBox.setBorder(new EmptyBorder(2, 5, 2, 5));
comboBox.setBackground(Color.WHITE);
add(comboBox);
lblLabel.setFont(new Font("Tahoma", Font.PLAIN, 11));
add(lblLabel);
}
public JComboBox getComboBox() {
return comboBox;
}
public JLabel getLabel() {
return lblLabel;
}
public void setText(String name) {
getLabel().setText(name);
}
}
HazardRenderer.java
public class HazardRenderer implements TreeCellRenderer {
private HazardComboBox leafRenderer = new HazardComboBox();
private DefaultTreeCellRenderer nonLeafRenderer = new DefaultTreeCellRenderer();
@Override
public Component getTreeCellRendererComponent(JTree tree, Object hazard, boolean selected, boolean expanded, boolean leaf,
int row, boolean hasFocus) {
if (leaf) {
leafRenderer.setText(hazard.toString());
return leafRenderer;
}
return nonLeafRenderer.getTreeCellRendererComponent(tree, hazard, selected, expanded, leaf, row, hasFocus);
}
}
HazardEditor.java
public class HazardEditor extends AbstractCellEditor implements TreeCellEditor {
private HazardRenderer renderer = new HazardRenderer();
private HazardComboBox component;
private DefaultMutableTreeNode treeNode;
//private ServerInfo info;
//private JComboBox comboBox;
private String val;
@Override
public Component getTreeCellEditorComponent(JTree tree, Object value,
boolean isSelected, boolean expanded, boolean leaf, int row) {
val = value.toString();
component = (HazardComboBox)renderer.getTreeCellRendererComponent(tree, value, isSelected, expanded, leaf, row, true);
if(leaf) {
treeNode = (DefaultMutableTreeNode)value;
component.setText(val);
//info = (ServerInfo)treeNode.getUserObject();
//comboBox = component.getComboBox();
ItemListener itemListener = new ItemListener() {
public void itemStateChanged(ItemEvent arg0) {
component.getComboBox().removeItemListener(this);
fireEditingStopped();
}
};
component.getComboBox().addItemListener(itemListener);
}
return component;
}
@Override
public Object getCellEditorValue() {
//info.setChecked(comboBox.isSelected());
//return info;
return null;
}
@Override
public boolean isCellEditable(EventObject event) {
if(!(event instanceof MouseEvent)) return false;
MouseEvent mouseEvent = (MouseEvent)event;
JTree tree = (JTree)event.getSource();
TreePath path = tree.getPathForLocation(mouseEvent.getX(), mouseEvent.getY());
if(path == null) return false;
Object lastComponent = path.getLastPathComponent();
if(lastComponent == null) return false;
DefaultMutableTreeNode treeNode = (DefaultMutableTreeNode)lastComponent;
return treeNode.isLeaf();
}
}
HazardSelection.java
public enum HazardSelection {
NOTCONSIDERED("Not Considered"), NOTAPPLICABLE("Not Applicable"), CONSIDERED("Considered"), HAZARD("Hazard");
private String name;
private HazardSelection (String n) {
name = n;
}
@Override
public String toString() {
return name;
}
}
问题是关于覆盖 HazardEditor.java
中的 getCellEditorValue()
方法。您已完成以下操作:
@Override
public Object getCellEditorValue() {
//info.setChecked(comboBox.isSelected());
//return info;
return null;
}
因此您要返回 null
,然后您的 Renderer
呈现 null 作为标签的文本。
您可以更正如下:
@Override
public Object getCellEditorValue() {
return component.getComboBox().getSelectedItem();
}
祝你好运。
我正在尝试将 JTree
中的 Renderer
用于我正在开发的 Swing 应用程序,仅当树是叶对象并且由流组成时才使用自定义渲染器布局。带有图像的空标签,JComboBox
最后是包含字符串的标签。
最初 Renderer
通过 HazardRenderer.java
中的 getTreeCellRendererComponent()
方法传递一个字符串值,然后使用 HazardComboBox.java
中的 setText()
方法设置然后编辑器获取选定的渲染器实例并使用相同的 setText()
方法设置文本。
但是,当在 HazardEditor()
中调用 ItemListener
时,标签文本会被清除。我可以验证这一点,因为注释掉侦听器可以消除问题,但我需要一个侦听器能够告诉应用程序编辑器的编辑已经可靠地完成。这个问题的解决方案是什么?下面的代码;
Main.java
public class Main {
public JComponent makeUI() {
JTree tree = new JTree();
tree.setEditable(true);
tree.setRootVisible(false);
tree.setCellRenderer(new HazardRenderer());
tree.setCellEditor(new HazardEditor());
//tree.setModel() excluded for brevity
return new JScrollPane(tree);
}
public static void main(String[] args) {
EventQueue.invokeLater(() -> {
JFrame f = new JFrame();
f.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
f.getContentPane().add(new Main().makeUI());
f.pack();
f.setLocationRelativeTo(null);
f.setVisible(true);
});
}
}
HazardComboBox.java
public class HazardComboBox extends JPanel {
private JLabel lblLabel = new JLabel("Placeholder");
private JComboBox comboBox = new JComboBox(HazardSelection.values());
public HazardComboBox() {
setBackground(Color.WHITE);
setLayout(new FlowLayout(FlowLayout.CENTER, 0, 0));
JLabel label = new JLabel("");
label.setIcon(new ImageIcon(HazardComboBox.class.getResource("/javax/swing/plaf/metal/icons/ocean/file.gif")));
add(label);
comboBox.setBorder(new EmptyBorder(2, 5, 2, 5));
comboBox.setBackground(Color.WHITE);
add(comboBox);
lblLabel.setFont(new Font("Tahoma", Font.PLAIN, 11));
add(lblLabel);
}
public JComboBox getComboBox() {
return comboBox;
}
public JLabel getLabel() {
return lblLabel;
}
public void setText(String name) {
getLabel().setText(name);
}
}
HazardRenderer.java
public class HazardRenderer implements TreeCellRenderer {
private HazardComboBox leafRenderer = new HazardComboBox();
private DefaultTreeCellRenderer nonLeafRenderer = new DefaultTreeCellRenderer();
@Override
public Component getTreeCellRendererComponent(JTree tree, Object hazard, boolean selected, boolean expanded, boolean leaf,
int row, boolean hasFocus) {
if (leaf) {
leafRenderer.setText(hazard.toString());
return leafRenderer;
}
return nonLeafRenderer.getTreeCellRendererComponent(tree, hazard, selected, expanded, leaf, row, hasFocus);
}
}
HazardEditor.java
public class HazardEditor extends AbstractCellEditor implements TreeCellEditor {
private HazardRenderer renderer = new HazardRenderer();
private HazardComboBox component;
private DefaultMutableTreeNode treeNode;
//private ServerInfo info;
//private JComboBox comboBox;
private String val;
@Override
public Component getTreeCellEditorComponent(JTree tree, Object value,
boolean isSelected, boolean expanded, boolean leaf, int row) {
val = value.toString();
component = (HazardComboBox)renderer.getTreeCellRendererComponent(tree, value, isSelected, expanded, leaf, row, true);
if(leaf) {
treeNode = (DefaultMutableTreeNode)value;
component.setText(val);
//info = (ServerInfo)treeNode.getUserObject();
//comboBox = component.getComboBox();
ItemListener itemListener = new ItemListener() {
public void itemStateChanged(ItemEvent arg0) {
component.getComboBox().removeItemListener(this);
fireEditingStopped();
}
};
component.getComboBox().addItemListener(itemListener);
}
return component;
}
@Override
public Object getCellEditorValue() {
//info.setChecked(comboBox.isSelected());
//return info;
return null;
}
@Override
public boolean isCellEditable(EventObject event) {
if(!(event instanceof MouseEvent)) return false;
MouseEvent mouseEvent = (MouseEvent)event;
JTree tree = (JTree)event.getSource();
TreePath path = tree.getPathForLocation(mouseEvent.getX(), mouseEvent.getY());
if(path == null) return false;
Object lastComponent = path.getLastPathComponent();
if(lastComponent == null) return false;
DefaultMutableTreeNode treeNode = (DefaultMutableTreeNode)lastComponent;
return treeNode.isLeaf();
}
}
HazardSelection.java
public enum HazardSelection {
NOTCONSIDERED("Not Considered"), NOTAPPLICABLE("Not Applicable"), CONSIDERED("Considered"), HAZARD("Hazard");
private String name;
private HazardSelection (String n) {
name = n;
}
@Override
public String toString() {
return name;
}
}
问题是关于覆盖 HazardEditor.java
中的 getCellEditorValue()
方法。您已完成以下操作:
@Override
public Object getCellEditorValue() {
//info.setChecked(comboBox.isSelected());
//return info;
return null;
}
因此您要返回 null
,然后您的 Renderer
呈现 null 作为标签的文本。
您可以更正如下:
@Override
public Object getCellEditorValue() {
return component.getComboBox().getSelectedItem();
}
祝你好运。