Outliner应用添加节点时点击OK输入框重复弹出问题求助
Outliner应用添加节点对话框重复弹出问题修复
问题描述
开发一款类似待办清单的Outliner应用,支持添加和编辑节点。添加节点时点击“OK”按钮后,输入对话框会重复弹出;已用布尔值修复“取消”按钮的问题,但OK按钮和对话框右上角的X按钮仍会导致输入框重新弹出。
控制器类代码
public class OutlinerController implements ActionListener { private OutlinerModel model; private OutlinerView view; public OutlinerController(OutlinerModel model, OutlinerView view) { this.model = model; this.view = view; // 注册控制器为视图中按钮的监听器 view.addButtonListener(this); view.addEditButtonListener(this); view.addDeleteButtonListener(this); view.addCompleteButtonListener(this); view.addSearchButtonListener(this); } public void actionPerformed(ActionEvent e) { DefaultMutableTreeNode selectedNode = (DefaultMutableTreeNode) view.getTree().getLastSelectedPathComponent(); if (e.getSource() == view.getAddButton()) { boolean adding = true; while (adding) { // 向选中节点添加新节点 String nodeName = JOptionPane.showInputDialog("Enter node name:"); if (nodeName == null) { // 点击取消按钮或右上角X adding = false; } else if (nodeName.trim().equals("")) { // 输入空名称 JOptionPane.showMessageDialog(view.getTree(), "Node name cannot be empty.", "Error", JOptionPane.ERROR_MESSAGE); } else { DefaultMutableTreeNode newNode = new DefaultMutableTreeNode(nodeName); model.getTreeModel().insertNodeInto(newNode, selectedNode, selectedNode.getChildCount()); // 展开选中节点以显示新添加的节点 view.getTree().expandPath(new TreePath(selectedNode.getPath())); // 添加成功后退出循环 adding = false; } } } if (e.getSource() == view.getEditButton()) { // 编辑选中节点的名称 String nodeName = JOptionPane.showInputDialog("Enter new node name:"); selectedNode.setUserObject(nodeName); model.getTreeModel().nodeChanged(selectedNode); } if (e.getSource() == view.getDeleteButton()) { // 从JTree中移除选中节点 model.getTreeModel().removeNodeFromParent(selectedNode); } if (e.getSource() == view.getCompleteButton()) { // 将选中节点标记为已完成 selectedNode.setUserObject(selectedNode.getUserObject() + " [Complete]"); model.getTreeModel().nodeChanged(selectedNode); } if (e.getSource() == view.getSearchButton()) { // 获取用户输入的搜索词 String searchTerm = JOptionPane.showInputDialog("Enter search term:"); DefaultMutableTreeNode searchResult = searchNode(model.getRoot(), searchTerm); // 如果找到匹配节点,选中并滚动到该节点 if (searchResult != null) { TreePath path = new TreePath(searchResult.getPath()); view.getTree().setSelectionPath(path); view.getTree().scrollPathToVisible(path); } else { // 未找到匹配节点时显示提示 view.displayErrorMessage("No node found with the given search term"); } } } private DefaultMutableTreeNode searchNode(DefaultMutableTreeNode node, String searchTerm) { // 检查当前节点是否匹配搜索词 if (node.getUserObject().toString().toLowerCase().contains(searchTerm.toLowerCase())) { return node; } // 递归搜索当前节点的子节点 for (int i = 0; i < node.getChildCount(); i++) { DefaultMutableTreeNode childNode = (DefaultMutableTreeNode) node.getChildAt(i); DefaultMutableTreeNode result = searchNode(childNode, searchTerm); if (result != null) { return result; } } // 未找到匹配节点时返回null return null; } private void searchNode(String searchString) { // 获取JTree的根节点 DefaultMutableTreeNode rootNode = (DefaultMutableTreeNode) view.getTree().getModel().getRoot(); // 遍历JTree查找匹配搜索字符串的节点 searchNodeHelper(searchString, rootNode); } private void searchNodeHelper(String searchString, DefaultMutableTreeNode node) { // 获取节点的用户对象并转换为小写 String nodeString = node.getUserObject().toString().toLowerCase(); // 检查节点字符串是否包含搜索字符串 if (nodeString.contains(searchString)) { // 如果匹配,展开路径并高亮节点 TreePath path = new TreePath(node.getPath()); view.getTree().expandPath(path); view.getTree().setSelectionPath(path); return; } // 如果不匹配,递归检查子节点 for (int i = 0; i < node.getChildCount(); i++) { DefaultMutableTreeNode childNode = (DefaultMutableTreeNode) node.getChildAt(i); searchNodeHelper(searchString, childNode); } } }
问题分析与修复
核心问题
添加节点的while(adding)循环中,当用户输入有效名称并成功添加节点后,未将adding设为false,导致循环持续执行,重复弹出输入对话框。
额外排查点
若点击对话框右上角X按钮仍出现重复弹出,需检查视图层OutlinerView中的addButtonListener方法是否被多次调用,导致监听器重复注册,进而多次触发actionPerformed方法。
修复步骤
- 在添加节点成功的分支中添加
adding = false;,确保完成一次添加后退出循环(已在上述代码中标记)。 - 检查
OutlinerView类,确保addButtonListener仅被调用一次,避免重复注册监听器。
内容的提问来源于stack exchange,提问作者Aaron
相关产品推荐
相关产品推荐

