Jtree就呈现与JCheckBox、节点
题
我试图修改标准的摆动jtree就混合在一起,节点与无选框。这是一个例子:
当我试图检查/取消一个框('用户01'节点,在这个例子),树失去了节点:
我在我的代码是一种适应这个例子: http://forums.sun.com/thread.jspa?threadID=5321084&start=13.
而不是嵌入一个JCheckBox、在DefaultMutableTreeNode这样的:
new DefaultMutableTreeNode(new CheckBoxNode("Accessibility", true));
我以为它作出更多意义上,创建一个模型节点,从DefaultMutableTreeNode,我呼JTreeNode.这类自动设定DefaultMutableTreeNode的UserObject到JCheckBox、.类'ShowCheckBox的财产所使用的TreeCellRenderer,以确定如果JCheckBox、或DefaultTreeCellRenderer是使用。该JTreeNode是使用这样的:
JTreeNode user01 = new JTreeNode("User 01");
user01.setShowCheckBox(true);
user01.setSelected(true);
我相信该问题是与该类实现TreeCellEditor,特别是在getCellEditorValue()或getTreeCellEditorComponent()方法。我怀疑这个问题具有的东西与getCellEditorValue()返回的一个衍生物的DefaultMutableTreeNode,而不是一个简单的模型的实例。
public Object getCellEditorValue() {
JCheckBox checkBox = renderer.getCheckBoxRenderer();
JTreeNode node = new JTreeNode(checkBox.getText());
node.setShowCheckBox(true);
node.setSelected(checkBox.isSelected());
return node;
}
public Component getTreeCellEditorComponent(JTree tree, Object value, boolean isSelected, boolean expanded, boolean leaf, int row) {
Component editor = renderer.getTreeCellRendererComponent(tree, value, true, expanded, leaf, row, true);
// editor always selected / focused
ItemListener itemListener = new ItemListener() {
public void itemStateChanged(ItemEvent itemEvent) {
if (stopCellEditing()) {
fireEditingStopped();
}
}
};
if (editor instanceof JCheckBox) {
((JCheckBox) editor).addItemListener(itemListener);
}
return editor;
}
这里是TreeCellRender的getTreeCellRendererComponent()方法:
public Component getTreeCellRendererComponent(JTree tree, Object value, boolean selected, boolean expanded, boolean leaf, int row, boolean hasFocus) {
Component component;
//if object being passed for rendering is a JTreeNode that should show a JCheckBox, attempt to render it so
if (((JTreeNode) value).getShowCheckBox()) {
String stringValue = tree.convertValueToText(value, selected, expanded, leaf, row, false);
//set default JCheckBox rendering
checkBoxRenderer.setText(stringValue);
checkBoxRenderer.setSelected(false); //not checked
checkBoxRenderer.setEnabled(tree.isEnabled());
if (selected) {
//removed colorization
//checkBoxRenderer.setForeground(selectionForeground);
//checkBoxRenderer.setBackground(selectionBackground);
}
else {
checkBoxRenderer.setForeground(textForeground);
checkBoxRenderer.setBackground(textBackground);
}
//DefaultMutableTreeNode
if ((value != null) && (value instanceof JTreeNode)) {
//userObject should be a JTreeNode instance
//DefaultMutableTreeNode
//Object userObject = ((JTreeNode) value).getUserObject();
//if it is
//if (userObject instanceof JTreeNode) {
//cast as a JTreeNode
//JTreeNode node = (JTreeNode) userObject;
JTreeNode node = (JTreeNode) value;
//set JCheckBox settings to match JTreeNode's settings
checkBoxRenderer.setText(node.getText());
checkBoxRenderer.setSelected(node.isSelected());
//}
}
component = checkBoxRenderer;
}
//if not, render the default
else {
component = defaultRenderer.getTreeCellRendererComponent(tree, value, selected, expanded, leaf, row, hasFocus);
}
return component;
}
任何想法都是极大的赞赏。
解决方案
我能够解决这个问题。
我创建的模型类(TreeNodeModel)以保持相关的节点数据:键,值,hasCheckBox,isSelected:
public class TreeNodeModel {
int key;
String value;
boolean isSelected=false;
boolean hasCheckBox=false;
public TreeNodeModel() {
}
public TreeNodeModel(int key, String value) {
this.key=key;
this.value = value;
}
public TreeNodeModel(int key, String value, boolean hasCheckBox) {
this.key=key;
this.value = value;
this.hasCheckBox = hasCheckBox;
}
public TreeNodeModel(int key, String value, boolean hasCheckBox, boolean isSelected) {
this.key=key;
this.value = value;
this.hasCheckBox=hasCheckBox;
this.isSelected = isSelected;
}
public boolean isSelected() {
return this.isSelected;
}
public void setSelected(boolean newValue) {
this.isSelected = newValue;
}
public boolean hasCheckBox() {
return this.hasCheckBox;
}
public void setCheckBox(boolean newValue) {
this.hasCheckBox=newValue;
}
public int getKey() {
return this.key;
}
public void setKey(int newValue) {
this.key = newValue;
}
public String getValue() {
return this.value;
}
public void setValue(String newValue) {
this.value = newValue;
}
@Override
public String toString() {
return getClass().getName() + "[" + this.value + "/" + this.isSelected + "]";
// return this.text;
}
}
我创建的TreeCellEditor接口的实现:
public class TreeNodeEditor extends AbstractCellEditor implements TreeCellEditor {
private JTree tree;
private TreeNodeModel editedModel = null;
TreeNodeRenderer renderer = new TreeNodeRenderer();
public TreeNodeEditor(JTree tree) {
this.tree=tree;
}
@Override
public boolean isCellEditable(EventObject event) {
boolean editable=false;
if (event instanceof MouseEvent) {
MouseEvent mouseEvent = (MouseEvent) event;
TreePath path = tree.getPathForLocation(mouseEvent.getX(),mouseEvent.getY());
if (path != null) {
Object node = path.getLastPathComponent();
if ((node != null) && (node instanceof DefaultMutableTreeNode)) {
DefaultMutableTreeNode editedNode = (DefaultMutableTreeNode) node;
TreeNodeModel model = (TreeNodeModel) editedNode.getUserObject();
editable = model.hasCheckBox;
} //if (node)
} //if (path)
} //if (MouseEvent)
return editable;
}
public Object getCellEditorValue() {
JCheckBox checkbox = renderer.getCheckBoxRenderer();
TreeNodeModel model = new TreeNodeModel(editedModel.getKey(), checkbox.getText(), true, checkbox.isSelected());
return model;
}
public Component getTreeCellEditorComponent(JTree tree, Object value, boolean isSelected, boolean expanded, boolean leaf, int row) {
if (((DefaultMutableTreeNode) value).getUserObject() instanceof TreeNodeModel) {
editedModel = (TreeNodeModel) ((DefaultMutableTreeNode) value).getUserObject();
}
Component editor = renderer.getTreeCellRendererComponent(tree, value, true, expanded, leaf, row, true);
// editor always selected / focused
ItemListener itemListener = new ItemListener() {
public void itemStateChanged(ItemEvent itemEvent) {
if (stopCellEditing())
fireEditingStopped();
}
};
if (editor instanceof JCheckBox) {
((JCheckBox) editor).addItemListener(itemListener);
}
return editor;
}
}
的关键是捕获模式在getTreeCellEditorComponent()方法和在getCellEditorValue()方法,使用它的密钥。
构建树很容易:
DefaultMutableTreeNode server = new DefaultMutableTreeNode(new TreeNodeModel(0,"Server 01", false));
DefaultMutableTreeNode userFolder = new DefaultMutableTreeNode(new TreeNodeModel(1, "User Folders", false));
server.add(userFolder);
DefaultMutableTreeNode user01 = new DefaultMutableTreeNode(new TreeNodeModel(2, "User 01", true, true));
userFolder.add(user01);
DefaultMutableTreeNode clientA = new DefaultMutableTreeNode(new TreeNodeModel(3, "Client A", true, true));
user01.add(clientA);
DefaultMutableTreeNode clientB = new DefaultMutableTreeNode(new TreeNodeModel(4, "Client B", true, true));
user01.add(clientB);
DefaultMutableTreeNode publicFolder = new DefaultMutableTreeNode(new TreeNodeModel(5, "Public Folders", false));
server.add(publicFolder);
DefaultMutableTreeNode clientC = new DefaultMutableTreeNode(new TreeNodeModel(6, "Client C", true));
publicFolder.add(clientC);
Tree_Nodes.setCellRenderer(new TreeNodeRenderer());
Tree_Nodes.setCellEditor(new TreeNodeEditor(Tree_Nodes));
Tree_Nodes.setModel(new DefaultTreeModel(server);
最后,确定哪些节点,其中检查是(通过按钮)检查模型的节点集合的问题:
private Map<Integer, String> checked = new HashMap<Integer, String>();
private void Button_CheckedActionPerformed(java.awt.event.ActionEvent evt) {
DefaultTableModel tableModel = ((DefaultTableModel) Table_Nodes.getModel());
tableModel.getDataVector().removeAllElements();
tableModel.fireTableDataChanged();
checked.clear();
DefaultTreeModel treeModel = (DefaultTreeModel) Tree_Nodes.getModel();
DefaultMutableTreeNode root = (DefaultMutableTreeNode) treeModel.getRoot();
getChildNodes(root);
for (Iterator it=checked.entrySet().iterator(); it.hasNext(); ) {
Map.Entry entry = (Map.Entry)it.next();
tableModel.addRow(new Object[] {entry.getKey(), entry.getValue()});
}
Button_Checked.requestFocus();
}
private void getChildNodes(DefaultMutableTreeNode parentNode) {
for (Enumeration e=parentNode.children(); e.hasMoreElements();) {
DefaultMutableTreeNode childNode = (DefaultMutableTreeNode) e.nextElement();
TreeNodeModel model = (TreeNodeModel) childNode.getUserObject();
if (model.hasCheckBox && model.isSelected()) {
checked.put(model.getKey(), model.getValue());
}
//recurse
if (childNode.getChildCount()>0) getChildNodes(childNode);
}
}
其他提示
这里有几个"陷阱",引起呈现的问题,对我说:
该TreeCellEditor可以不分享TreeCellRenderer实例通过成为
JTree.setCellRenderer()
.如果TreeCellEditor.getTreeCellEditorComponent()
返回同一个实例如树的TreeCellRenderer.getTreeCellRendererComponent()
你将最终呈现的问题。你会试图编辑一个细胞,但是所呈示是针对5个不相关的细胞。当编辑的尝试,以检索的JCheckBox、国家将获得的价值从上次呈现单元(相对于最后的编辑元),这显然是错误的。使用
TreeCellEditor.getCellEditorValue()
修改的细胞的价值,而不是添加鼠听众直接选项。这种方法只得到援引的值得保存。如果你立即采取行动,对小鼠的事件的价值不会回滚CellEditor.cancelCellEditing()
.