关于具有多个视图的单个模型的操作和使用的实施的不确定性 [英] Uncertainties regarding Implementation of Actions and Usage of a single Model with multiple Views

查看:20
本文介绍了关于具有多个视图的单个模型的操作和使用的实施的不确定性的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我是 GUI 编程的新手,也许我的问题是一个非常简单的解决方案.我正在尝试实现一个 Java Swing GUI 作为树状数据结构的编辑器.GUI分为三个部分:

I'm a total newbee regarding GUI programming and maybe my problem has a quite simple solution. I'm trying to implement a Java Swing GUI that serves as an editor for a tree like data structure. The GUI is divided into three parts:

  1. 窗口左侧四分之一的树查看器显示树结构数据.

  1. A tree viewer in the left quarter of the window displays the tree structured data.

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

The large upper right area displays editors containing text fields, tables and the like. Each different kind of object in the tree structure has its own editor which is shown when it is selected in the tree viewer.

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

The lower right area shows a console viewer. It is used to display messages about specific actions.

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

I'm trying hard to obey a strict separation of the model from its visualization in the tree viewers/editors in my program. Therefore I created an instance of a sub-class of DefaultTreeModel (MyTreeModel) which stores references to the business data and an instance of a sub-class of JTree that provides the visual representation of the tree structure.

我正在尝试实现使用以下方法修改数据的功能动作类.任何操作(如 CreateNode、RenameNode、DeleteNode)在它自己的动作类(AbstractAction 的子类)中实现.这些操作用于树查看器的上下文菜单和应用程序编辑"菜单.但我也想重用其中的一些GUI 的编辑器部分,例如RenameNode 操作.我在这里目前卡住了.

I'm attempting to implement functionality that modifies the data using Action classes. Any action (like CreateNode, RenameNode, DeleteNode) is implemented in it's own action class (sub-class of AbstractAction). The actions are used in the tree viewer's context menu and in the applications "Edit" menu. But I also want to reuse some of them in the editor parts of the GUI, e.g. the RenameNode action. And here I'm currently stuck.

树查看器显示一个图标以及每个节点的名称那个树.并且相应的编辑器包含,除其他外东西,也是一个显示关联节点名称的 JTextField.

The tree viewer displays an icon along with the name for every node in the tree. And the respective editor contains, among other stuff, also a JTextField that shows the associated node's name.

我知道我可以将动作对象附加到 JMenu、JPopupMenu 和甚至是使用 setAction 方法的 JTextField 对象.一世这样做了,现在我在程序的编辑"中有一个重命名"菜单项menue,在与代表的 JTree 关联的弹出菜单中树查看器和显示节点名称的 JTextField 也有这个操作附加到它.

I know that I can attach action objects to JMenu, JPopupMenu and even to JTextField objects using the setAction method. I did so and now I have a "Rename" menue entry in the program's "Edit" menue, in the popup menue associated with the JTree that represents the tree viewer and the JTextField showing the node name also has this action attached to it.

要更改树节点的名称"属性,我创建了类RenameNode 作为 AbstractAction 的子类.正如已经提到的名称显示在树查看器中的每个节点处,操作只是使此文本可编辑.执行此操作的代码如下所示(在类 RenameNode 中):

To change the "Name" attribute of a tree node, I created the class RenameNode as a sub-class of AbstractAction. As already mentioned the name is displayed at each node in the tree viewer and the action simply makes this text editable. The code doing this looks as follows (in the class RenameNode):

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());
    }
}

需要这些 if 语句来使操作正常工作:

These if statements are needed to make the action work properly from:

-- 弹出菜单(第一个 if 语句;这里是下面的对象弹出菜单打开时的鼠标是可编辑的)

-- the popup menu (first if statement; here the object which was under the mouse when the popup menu is opened is made editable)

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

-- the application's menu (second if statement; here the tree node that is currently selected -- if any -- is made editable).

嗯,这在原则上很好用,但实际上是重命名节点不是通过 RenameAction 类中的代码完成的actionPerformed(ActionEvent ev) 方法.节点的真正变化name 在树的 MyTreeModel 类中的方法中执行valueForPathChanged() 被覆盖如下:

Well, this works fine, in principle but in fact the renaming of the node is not done through the code in the RenameAction class's actionPerformed(ActionEvent ev) method. The real change of the node's name is executed in the tree's MyTreeModel class in the method valueForPathChanged() which is overridden as follows:

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 应该与树模型结构中的单个节点相关联,作为其模型和附加的操作应该修改该模型以及何时模型已更改,树查看器需要收到通知才能更新树查看器中相应节点的名称.

I have absolutely no clue how the concept of actions could properly be applied here. Even worse is the situation with the rename operation when it is performed changing the text in the JTextField object. At the moment I don't know how to implement that in a clean way. The JTextField should get associated with a single node from the tree model structure as its model and the attached action should modify that model and when this model is changed the tree viewer would need to get notified to update the respective node's name in the tree viewer.

我假设 MyNode 类(它是DefaultMutableTreeNode) 必须实现接口 Document并且 RenameAction 类必须修改它,然后是一个事件将必须发出通知显示树查看器改变了节点.

I assume that the MyNode class (which is alrady a sub-class of DefaultMutableTreeNode) would have to implement the interface Document and the RenameAction class would have to modify it and then an event would have to be issued to notify the tree viewer that displays the changed node.

底线:我必须承认我还没有完全理解如何正确实施将在多个地方使用的操作在 GUI 中,我不完全了解如何实现模型可以被多个 GUI 对象使用(在我的例子中是 JTree 和JTextField).可能这一切都很简单......

Bottom line: I must admit that I did not yet completely understand how to properly implement an action that is to be used in multiple places in a GUI and I don't completely understand how to implement a model that can be used by multiple GUI objects (in my case a JTree and a JTextField). Possibly all that is quite simple ...

在此先感谢您的帮助!

嗯,给出的答案非常有助于解释行动如何可以与 JTrees 一起使用.但还有一点我想讨论.在我的 GUI 中,我组合了业务数据的树形表示带有数据编辑器(位于窗口左侧四分之一的树,旁边是节点类型特定的编辑器).所有节点都有可以更改的名称.而且,编辑器包含一个文本字段(使用 JTextField 实现),其中显示节点的名称并且也可以对其进行编辑.我的不确定性如下:JTextField 允许分配一个动作对象以及一个为它建模.实际上,模型将是一个已在 JTree 中查看的节点对象.我认为应该有一种方法可以将 JTree 中使用的相同模型对象也用作编辑器中 JTextField 的模型,并在那里重用 Action 类.关于模型的重用,我认为我的模型类 MyTreeNode 也必须实现 Document 接口,对吗?并且在调出节点特定的编辑器时,我必须使用其 setDocument() 方法将 JTree 中当前选择的节点与 JTextField 对象相关联.最后我的 RenameNodeAction 将不得不执行JTextField 的节点名称.所以我的中心点是:让一个模型在多个视图中显示,并且在要重命名节点的任何地方只重用一个 RenameAction.这是否有意义?我的想法是否可行?

Well the answers given were quite helpful in explaining how actions can be used together with JTrees. But there is one more point I'd like to discuss. In my GUI I have a tree representation of my business data combined with editors for the data (the tree located in the left quarter of the window and aside of it a node type specific editor). All the nodes have names that can be changed. And, the editors contain a text field (implemented with a JTextField) in which the node's name is displayed and which can be edited too. My uncertainty here is as follows: A JTextField allows to assign an action object as well as a model to it. Actually the model would be a node object already viewed in the JTree. I think there should be a way to use the same model object used in the JTree also as a model for the JTextField in the editor and also reuse the Action class there. Regarding the reuse of the model I think my model class MyTreeNode will have to implement the Document interface too, correct? And when bringing up the node specific editor I'd have to associate the node currently selected in the JTree with the JTextField object using its setDocument() method. Finally my RenameNodeAction would have to perform the change of the JTextField's node's name. So my central point is: making one model being displayd in multiple views and the reuse of just one RenameAction everywhere where a node is to be renamed. Does this make sense and is my idea how this must be accomplished feasible?

推荐答案

超出 Stackoverflow 范围的应用程序设计的完整指南.相反,从 中显示的示例 TreeIconDemo 开始如何使用树.请注意它如何将 TreeSelectionListener 添加到 tree 以更新附近的 JEditorPane.现在,将另一个 TreeSelectionListener 添加到不同的视图,以查看如何更新新视图.您可能还会从这个相关的答案中获得一些见解.

A complete guide to application design in beyond the scope of Stackoverflow. Instead, start with the example TreeIconDemo shown in How to Use Trees. Notice how it adds a TreeSelectionListener to the tree in order to update a nearby JEditorPane. Now, add another TreeSelectionListener to a different view to see how you could update the new view, too. You might also get some insight from this related answer.

附录:从此示例开始,您可以执行以下操作.更改选择会更新 textField 以显示所选节点的名称.编辑节点(通常是 F2)或 textField 会更改所选节点的名称.

Addendum: Starting from this example, you can do something like the following. Changing the selection updates the textField to show the selected node's name. Editing either the node (typically F2) or the textField changes the selected node's name.

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);
            }
        }
    }
});

这篇关于关于具有多个视图的单个模型的操作和使用的实施的不确定性的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆