问题
I am trying to use a Renderer
in a JTree
for a Swing application I am developing, the custom renderer is used only when the tree is a leaf object and is composed of a flow layout. An empty label with an image, a JComboBox
and finally a label that contains a String.
Initially the Renderer
is passed a string value via the getTreeCellRendererComponent()
method in HazardRenderer.java
it is then set using the setText()
method in HazardComboBox.java
the editor then takes the selected renderer instance and sets text using the same setText()
method.
However the label text is cleared out when the ItemListener
is called within HazardEditor()
. I can verify this because commenting out the listener removes the issue, but I require a listener to be able to tell the application that editing the editor has finished reliably. What is the solution to this problem? Code below;
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;
}
}
回答1:
The problem is about overriding the getCellEditorValue()
method in HazardEditor.java
. You have done this as follow:
@Override
public Object getCellEditorValue() {
//info.setChecked(comboBox.isSelected());
//return info;
return null;
}
So you are returning null
, then your Renderer
renders null as the label's text.
You can correct it as follow:
@Override
public Object getCellEditorValue() {
return component.getComboBox().getSelectedItem();
}
Good Luck.
来源:https://stackoverflow.com/questions/34991034/jtree-editor-not-setting-variables