gpt4 book ai didi

java - 复选框树未按预期工作

转载 作者:行者123 更新时间:2023-12-01 13:18:17 25 4
gpt4 key购买 nike

我想创建一棵具有给定节点和子节点的树。所需的行为如下:

“当切换节点的复选框时,它的新值(选中/未选中)应该反射(reflect)到它的所有后代”

以下是完整代码,但没有给出预期的行为:

    public class CheckBoxTree {

Map<String, DefaultMutableTreeNode> nodes = new HashMap<String, DefaultMutableTreeNode>();

public static void main(final String args[]) {
final CheckBoxTree cbt = new CheckBoxTree();
DefaultMutableTreeNode root = cbt.addNodeWithoutCheckbox(null, "Select divisions");

DefaultMutableTreeNode nodeSTD1 = cbt.addNodeWithCheckbox(root, "STD1", false);
cbt.nodes.put("STD1", nodeSTD1);
DefaultMutableTreeNode nodeDiv1 = cbt.addNodeWithCheckbox(nodeSTD1, "DIV1", false);
cbt.nodes.put("DIV1", nodeDiv1);
DefaultMutableTreeNode nodeDiv2 = cbt.addNodeWithCheckbox(nodeSTD1, "DIV2", false);
cbt.nodes.put("DIV2", nodeDiv2);

root.add(nodeSTD1);

DefaultMutableTreeNode nodeSTD2 = cbt.addNodeWithCheckbox(root, "STD2", false);
cbt.nodes.put("STD2", nodeSTD2);
DefaultMutableTreeNode nodeDiv3 = cbt.addNodeWithCheckbox(nodeSTD2, "DIV3", false);
cbt.nodes.put("DIV3", nodeDiv3);
DefaultMutableTreeNode nodeDiv4 = cbt.addNodeWithCheckbox(nodeSTD2, "DIV4", false);
cbt.nodes.put("DIV4", nodeDiv4);
root.add(nodeSTD2);

final JTree tree = cbt.createCheckBoxTree(root);

// show the tree onscreen
final JFrame frame = new JFrame("CheckBox Tree");
JPanel panel = new JPanel();
panel.setLayout(new BorderLayout());
panel.add(tree, BorderLayout.CENTER);
JButton button = new JButton("Submit");
panel.add(button, BorderLayout.SOUTH);
final JScrollPane scrollPane = new JScrollPane(panel);
frame.getContentPane().add(scrollPane, BorderLayout.CENTER);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(300, 150);
frame.setVisible(true);

button.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent arg0) {
/*TreePath[] selectionPaths = tree.getSelectionModel().getSelectionPaths();
// TreePath[] selectionPaths = tree.getSelectionPaths();
if (selectionPaths != null) {
System.out.println("Selected paths:");
for (TreePath tp : selectionPaths) {
System.out.println(tp);
}
}*/
System.out.println("Selected paths:");
for (DefaultMutableTreeNode n : cbt.nodes.values()) {
Object obj = n.getUserObject();
if (obj instanceof CheckBoxNode) {
if (((CheckBoxNode) obj).isSelected()) {
System.out.println(n.toString());
}
}
}
}
});

}

private JTree createCheckBoxTree(final DefaultMutableTreeNode root) {
final DefaultTreeModel treeModel = new DefaultTreeModel(root);
final JTree tree = new JTree(treeModel);

final CheckBoxNodeRenderer renderer = new CheckBoxNodeRenderer();
tree.setCellRenderer(renderer);

final CheckBoxNodeEditor editor = new CheckBoxNodeEditor(tree);
tree.setCellEditor(editor);
tree.setEditable(true);

// listen for changes in the model (including check box toggles)
treeModel.addTreeModelListener(new TreeModelListener() {

@Override
public void treeNodesChanged(final TreeModelEvent e) {
System.out.println(System.currentTimeMillis() + ": nodes changed");

DefaultMutableTreeNode node =
(DefaultMutableTreeNode) tree.getLastSelectedPathComponent();
if (node == null) {
return;
}
changeSubTreeSelections(node, null);
}

@Override
public void treeNodesInserted(final TreeModelEvent e) {
System.out.println(System.currentTimeMillis() + ": nodes inserted");
}

@Override
public void treeNodesRemoved(final TreeModelEvent e) {
System.out.println(System.currentTimeMillis() + ": nodes removed");
}

@Override
public void treeStructureChanged(final TreeModelEvent e) {
System.out.println(System.currentTimeMillis() + ": structure changed");
}
});

// listen for changes in the selection
tree.addTreeSelectionListener(new TreeSelectionListener() {
@Override
public void valueChanged(TreeSelectionEvent arg0) {
System.out.println(System.currentTimeMillis() + ": value changed");
/*DefaultMutableTreeNode node =
(DefaultMutableTreeNode) tree.getLastSelectedPathComponent();
if (node == null) {
return;
}
changeSubTreeSelections(node, null);*/
}
});

return tree;
}

protected void changeSubTreeSelections(DefaultMutableTreeNode node, Boolean selected) {
/*change all subtree selection if applicable*/
Object obj = node.getUserObject();
Boolean isSelected = selected;
if (obj instanceof CheckBoxNode) {
CheckBoxNode cbn = (CheckBoxNode) obj;
if (isSelected == null) {
isSelected = cbn.isSelected();
} else {
cbn.setSelected(isSelected);
}
} else {
return;
}
int count = node.getChildCount();
for (int i = 0; i < count; i++) {
DefaultMutableTreeNode child = (DefaultMutableTreeNode) node.getChildAt(i);
changeSubTreeSelections(child, isSelected);
}
}

public DefaultMutableTreeNode addNodeWithCheckbox(
final DefaultMutableTreeNode parent, final String text, final boolean checked) {
final CheckBoxNode data = new CheckBoxNode(text, checked);
final DefaultMutableTreeNode node = new DefaultMutableTreeNode(data);
if (parent != null) {
parent.add(node);
}
return node;
}

public DefaultMutableTreeNode addNodeWithoutCheckbox(
final DefaultMutableTreeNode parent, final String text) {
final DefaultMutableTreeNode node = new DefaultMutableTreeNode(text);
if (parent != null) {
parent.add(node);
}
return node;
}

/*private static DefaultMutableTreeNode add(
final DefaultMutableTreeNode parent, final String text, final boolean checked) {
final CheckBoxNode data = new CheckBoxNode(text, checked);
final DefaultMutableTreeNode node = new DefaultMutableTreeNode(data);
parent.add(node);
nodes.put(text, node);
return node;
}*/

}

class CheckBoxNodeRenderer implements TreeCellRenderer {

private JCheckBox checkBoxNodeRenderer = new JCheckBox();
private DefaultTreeCellRenderer nonCheckBoxNodeRenderer = new DefaultTreeCellRenderer();
private Color selectionBorderColor, selectionForegroundColor, selectionBackgroundColor,
textForegroundColor, textBackgroundColor;

protected JCheckBox getLeafCheckBox() {
return checkBoxNodeRenderer;
}

public CheckBoxNodeRenderer() {
Font fontValue;
fontValue = UIManager.getFont("Tree.font");
if (fontValue != null) {
checkBoxNodeRenderer.setFont(fontValue);
}
Boolean booleanValue = (Boolean) UIManager.get("Tree.drawsFocusBorderAroundIcon");
checkBoxNodeRenderer.setFocusPainted((booleanValue != null)
&& (booleanValue.booleanValue()));
selectionBorderColor = UIManager.getColor("Tree.selectionBorderColor");
selectionForegroundColor = UIManager.getColor("Tree.selectionForeground");
selectionBackgroundColor = UIManager.getColor("Tree.selectionBackground");
textForegroundColor = UIManager.getColor("Tree.textForeground");
textBackgroundColor = UIManager.getColor("Tree.textBackground");
}

@Override
public Component getTreeCellRendererComponent(
JTree tree, Object value, boolean selected, boolean expanded, boolean leaf, int row,
boolean hasFocus) {
Component returnValue;
/*check if it is checkbox object*/
boolean isCheckboxObject = false;
if ((value != null) && (value instanceof DefaultMutableTreeNode)) {
Object userObject = ((DefaultMutableTreeNode) value).getUserObject();
if (userObject instanceof CheckBoxNode) {
isCheckboxObject = true;
CheckBoxNode node = (CheckBoxNode) userObject;
checkBoxNodeRenderer.setText(node.getText());
checkBoxNodeRenderer.setSelected(node.isSelected());
}
} else {
String stringValue =
tree.convertValueToText(value, selected, expanded, leaf, row, false);
checkBoxNodeRenderer.setText(stringValue);
checkBoxNodeRenderer.setSelected(false);
}
if (isCheckboxObject) {
checkBoxNodeRenderer.setEnabled(tree.isEnabled());
if (selected) {
checkBoxNodeRenderer.setForeground(selectionForegroundColor);
checkBoxNodeRenderer.setBackground(selectionBackgroundColor);
} else {
checkBoxNodeRenderer.setForeground(textForegroundColor);
checkBoxNodeRenderer.setBackground(textBackgroundColor);
}
returnValue = checkBoxNodeRenderer;
} else {
returnValue =
nonCheckBoxNodeRenderer.getTreeCellRendererComponent(tree, value, selected,
expanded, leaf, row, hasFocus);
}
return returnValue;
}
}

class CheckBoxNodeEditor extends AbstractCellEditor implements TreeCellEditor {
private static final long serialVersionUID = 1L;

private CheckBoxNodeRenderer renderer = new CheckBoxNodeRenderer();
private ChangeEvent changeEvent = null;
private JTree tree;

public CheckBoxNodeEditor(JTree tree) {
this.tree = tree;
}

@Override
public Object getCellEditorValue() {
JCheckBox checkbox = renderer.getLeafCheckBox();
CheckBoxNode checkBoxNode = new CheckBoxNode(checkbox.getText(), checkbox.isSelected());
return checkBoxNode;
}

@Override
public boolean isCellEditable(EventObject event) {
/*uncomment following code to make all nodes editable*/
// return true;

// make all nodes, which are instance of CheckBoxNode, editable
boolean returnValue = 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 treeNode = (DefaultMutableTreeNode) node;
Object userObject = treeNode.getUserObject();
returnValue = (userObject instanceof CheckBoxNode);
// returnValue = ((treeNode.isLeaf()) && (userObject
// instanceof CheckBoxNode));
}
}
}
return returnValue;
}

@Override
public Component getTreeCellEditorComponent(
JTree tree, Object value, boolean selected, boolean expanded, boolean leaf, int row) {
Component editor =
renderer.getTreeCellRendererComponent(tree, value, false, 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;
}
}

class CheckBoxNode {

private String text;
private boolean selected;

public CheckBoxNode(String text, boolean selected) {
this.text = text;
this.selected = selected;
}

public boolean isSelected() {
return selected;
}

public void setSelected(boolean newValue) {
selected = newValue;
}

public String getText() {
return text;
}

public void setText(String newValue) {
text = newValue;
}

/*@Override
public String toString() {
return getClass().getName() + "[" + text + "/" + selected + "]";
}*/
@Override
public String toString() {
return text;
}
}

class NamedVector extends Vector<Object> {
private static final long serialVersionUID = 1L;

private String name;

public NamedVector(String name) {
this.name = name;
}

public NamedVector(String name, Object elements[]) {
this.name = name;
for (int i = 0, n = elements.length; i < n; i++) {
add(elements[i]);
}
}

@Override
public String toString() {
return "[" + name + "]";
}
}

任何父节点复选框的切换都无法在子节点中正确反射(reflect)。

请帮我理解问题出在哪里。

最佳答案

添加treeDidChange以重新绘制树。

@Override
public void treeNodesChanged(final TreeModelEvent e) {
System.out.println(System.currentTimeMillis() + ": nodes changed");

DefaultMutableTreeNode node = (DefaultMutableTreeNode) tree.getLastSelectedPathComponent();
if (node == null) {
return;
}
changeSubTreeSelections(node, null);
tree.treeDidChange();
}

而且,我发现在函数changeSubTreeSelections中,这行isSelected = !(cbn.isSelected());是不正确的。您不应该使用 ! 来获取相反的值。

如果选择了父节点,也许最好展开整个后代的路径。

关于java - 复选框树未按预期工作,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22281348/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com