Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/postgresql/9.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 关于操作实施和具有多个视图的单个模型使用的不确定性_Java_Swing_Model View Controller - Fatal编程技术网

Java 关于操作实施和具有多个视图的单个模型使用的不确定性

Java 关于操作实施和具有多个视图的单个模型使用的不确定性,java,swing,model-view-controller,Java,Swing,Model View Controller,我对GUI编程完全是个新手,也许我的问题已经解决了 一个非常简单的解决方案。 我正在尝试实现一个JavaSwingGUI,作为 用于树状数据结构的编辑器。GUI分为三个部分 部分: 窗口左四分之一处的树查看器显示 树结构数据 右上角的大区域显示包含文本字段的编辑器, 桌子之类的。树中每种不同类型的对象 结构有自己的编辑器,当在 树查看器 右下角区域显示控制台查看器。它用于显示 有关特定操作的消息 我正努力遵守严格的模型与模型的分离 在我的程序的树查看器/编辑器中进行可视化。所以我 创建Defau

我对GUI编程完全是个新手,也许我的问题已经解决了 一个非常简单的解决方案。 我正在尝试实现一个JavaSwingGUI,作为 用于树状数据结构的编辑器。GUI分为三个部分 部分:

  • 窗口左四分之一处的树查看器显示 树结构数据

  • 右上角的大区域显示包含文本字段的编辑器, 桌子之类的。树中每种不同类型的对象 结构有自己的编辑器,当在 树查看器

  • 右下角区域显示控制台查看器。它用于显示 有关特定操作的消息

  • 我正努力遵守严格的模型与模型的分离 在我的程序的树查看器/编辑器中进行可视化。所以我 创建DefaultTreeModel(MyTreeModel)子类的实例 它存储对业务数据的引用和 提供树的可视化表示的JTree的子类 结构

    我正在尝试实现使用 动作类。任何操作(如CreateNode、RenameNode、DeleteNode) 在它自己的action类(AbstractAction的子类)中实现。 这些操作在树查看器的上下文菜单和中使用 应用程序“编辑”菜单。但我也希望在中重用其中的一些 编辑器是GUI的一部分,例如重命名节点操作。我来了 现在卡住了

    树查看器将显示一个图标以及中每个节点的名称 那棵树。相应的编辑器包含 stuff,也是一个显示关联节点名称的JTextField

    private JTextField textField = new JTextField(10);
    ...
    final DefaultTreeModel treeModel = new DefaultTreeModel(root);
    tree = new JTree(treeModel);
    tree.addTreeSelectionListener(new TreeSelectionListener() {
    
        @Override
        public void valueChanged(TreeSelectionEvent e) {
            TreePath path = e.getNewLeadSelectionPath();
            if (path != null) {
                DefaultMutableTreeNode node =
                    (DefaultMutableTreeNode) path.getLastPathComponent();
                if (node.isLeaf()) {
                    Resource user = (Resource) node.getUserObject();
                    textField.setText(user.toString());
                } else {
                    textField.setText("");
                }
            }
        }
    });
    textField.addActionListener(new AbstractAction("edit") {
    
        @Override
        public void actionPerformed(ActionEvent e) {
            TreePath path = tree.getSelectionPath();
            if (path != null) {
                DefaultMutableTreeNode node =
                    (DefaultMutableTreeNode) path.getLastPathComponent();
                if (node.isLeaf()) {
                    String s = textField.getText();
                    Resource user = (Resource) node.getUserObject();
                    user.setName(s);
                    treeModel.reload(node);
                }
            }
        }
    });
    
    我知道我可以将动作对象附加到JMenu、jpopmpmenu和 甚至可以使用setAction方法创建JTextField对象。我 这样做了,现在我在程序的“编辑”中有一个“重命名”菜单项 菜单,在与表示 树查看器和显示节点名称的JTextField也有 附带的行动

    为了更改树节点的“Name”属性,我创建了这个类 重命名为AbstractAction的子类。如前所述 名称显示在树查看器和操作的每个节点上 只是使此文本可编辑。执行此操作的代码如下所示 (在重命名节点类中):

    需要这些if语句才能使操作从以下方面正常工作:

    --弹出菜单(第一个if语句;此处为 打开弹出菜单时的鼠标可编辑)

    --应用程序的菜单(第二个if语句;这里是树节点 当前选中的(如果有)将被设置为可编辑)

    好吧,这在原则上很好,但实际上 节点不是通过RenameAction类的 actionPerformed(ActionEvent ev)方法。节点属性的真实变化 name在方法中树的MyTreeModel类中执行 valueForPathChanged(),其覆盖方式如下:

    public class MyTreeModel extends DefaultTreeModel {
    
    
    [...]
    
        @Override
        public void valueForPathChanged(TreePath path, Object newValue) {
        final MyTreeNode aNode = (MyTreeNode)path.getLastPathComponent();
        if (newValue instanceof String) {
            ((MyNode) aNode.getUserObject()).setName((String) newValue);
        } else {
            aNode.setUserObject(newValue);
        }
            nodeChanged(aNode);
        }
    
    [...]
    
    }
    
    我完全不知道行动的概念是如何恰当地表达出来的 在这里申请。 更糟糕的是,重命名操作在运行时的情况 已执行更改JTextField对象中的文本的操作。此刻我 我不知道如何以干净的方式实现这一点。JTextField应该 从树模型结构中将单个节点关联为其 模型和附加的操作应修改该模型,以及何时修改该模型 模型已更改,树查看器需要得到更新通知 树查看器中相应节点的名称

    我假设MyNode类(它始终是 DefaultMutableTreeNode)必须实现接口文档 RenameAction类必须修改它,然后修改一个事件 必须发出通知以通知显示 已更改节点

    一句话:我必须承认,我还没有完全明白怎么做 正确地执行将在多个位置使用的操作 在GUI中,我不完全理解如何实现模型 可以由多个GUI对象使用(在我的例子中是JTree和 JTextField)。可能所有这些都很简单

    提前感谢您的帮助

    给出的答案对解释行动是如何进行的很有帮助 可与JTrees一起使用。但还有一点我想讨论。 在我的GUI中,我有一个业务数据的树表示 使用数据编辑器(位于窗口左四分之一处的树,旁边是特定于节点类型的编辑器)。所有节点都有可以更改的名称。并且,编辑器包含一个文本字段(使用JTextField实现),其中显示节点的名称,也可以对其进行编辑。我的不确定性如下: JTextField允许分配操作对象和 模仿它。实际上,模型将是已经在JTree中查看的节点对象。我认为应该有一种方法可以使用JTree中使用的相同模型对象,也可以作为编辑器中JTextField的模型,并且还可以重用那里的Action类。关于模型的重用,我认为我的模型类MyTreeNode也必须实现文档接口,对吗?当打开特定于节点的编辑器时,我必须使用其setDocument()方法将当前在JTree中选择的节点与JTextField对象相关联。 最后,我的RenameNodeAction必须执行 JTextField的节点名称。
    因此,我的中心观点是:在多个视图中显示一个模型,并在要重命名节点的任何位置重用一个重命名操作。这有意义吗?我的想法是如何做到这一点是可行的吗?

    哇,太详细了!谢谢

    好的,我对
    JTable
    做了类似的操作(插入/删除行)

    基本上你需要一个
    动作
    
    public class RenameNodeAction extends AbstractAction {
    
        private JTree tree;
        public RenameNodeAction(JTree tree) {
            this.tree = tree;
    
            // Initialise action as you require...
        }
    
        // Access to the tree, provide mostly so you can extend the action
        public JTree getTree() {
            return tree;
        }
    
        public void actionPerformed(ActionEvent evt) {
    
            JTree tree = getTree();
            TreePath path = tree.getSelectionPath();
            if (path != null && tree.isPathEditable(path)) {
                tree.startEditingAtPath(path);
            }
    
        }
    }
    
    private JTextField textField = new JTextField(10);
    ...
    final DefaultTreeModel treeModel = new DefaultTreeModel(root);
    tree = new JTree(treeModel);
    tree.addTreeSelectionListener(new TreeSelectionListener() {
    
        @Override
        public void valueChanged(TreeSelectionEvent e) {
            TreePath path = e.getNewLeadSelectionPath();
            if (path != null) {
                DefaultMutableTreeNode node =
                    (DefaultMutableTreeNode) path.getLastPathComponent();
                if (node.isLeaf()) {
                    Resource user = (Resource) node.getUserObject();
                    textField.setText(user.toString());
                } else {
                    textField.setText("");
                }
            }
        }
    });
    textField.addActionListener(new AbstractAction("edit") {
    
        @Override
        public void actionPerformed(ActionEvent e) {
            TreePath path = tree.getSelectionPath();
            if (path != null) {
                DefaultMutableTreeNode node =
                    (DefaultMutableTreeNode) path.getLastPathComponent();
                if (node.isLeaf()) {
                    String s = textField.getText();
                    Resource user = (Resource) node.getUserObject();
                    user.setName(s);
                    treeModel.reload(node);
                }
            }
        }
    });
    
    public class RenameNode extends AbstractAction
            implements TreeSelectionListener, CellEditorListener { 
    
        // Replace with whatever you're storing your text fields with
        private FieldStorage fields;
    
        private JTree tree;
    
        public RenameNode(FieldStorage fields, JTree tree) {
            this.fields = fields;
            this.tree = tree;
        }
    
        public void actionPerformed(ActionEvent ev) {
            // "mouseOverPath" is the Treepath were the mouse was placed on
            // when the popup menu was opened
            if (tree.existsMouseOverPath()) {
                tree.startEditingAtPath(tree.mouseOverPath);
            } else if (tree.getSelectionCount() != 0) {
                tree.startEditingAtPath(tree.getSelectionPath());
            }
        }
    
        public void valueChanged(TreeSelectionEvent e) {
            tree.startEditingAtPath(tree.getSelectionPath());
            setFieldText();
        }
    
        public void editingCanceled(ChangeEvent e) {
            // empty
        }
    
        public void editingStopped(ChangeEvent e) {
            setFieldText();
        }
    
        private void setFieldText() {
            MyTreeNode node = (MyTreeNode) tree.getSelectionPath()
                    .getLastPathComponent();
            String text = node.getUserObject().toString();
            fields.getFieldFor(node).setText(text);
        }
    
    }
    
    RenameNode renameNodeAction = new RenameNode(fields, tree);
    tree.addTreeSelectionListener(renameNodeAction);
    
    // editor is your TreeCellEditor. Can be the DefaultTreeCellEditor
    // if you haven't already made your own
    editor.addCellEditorListener(renameNodeAction);
    tree.setCellEditor(editor);
    tree.setEditable(true);