【问题标题】:Using Actions with DocumentListener将动作与 DocumentListener 一起使用
【发布时间】:2011-11-11 18:33:42
【问题描述】:

我正在开发一个应用程序,我希望用户更新 JTextArea 的内容或通过按下 JButton 手动触发某些东西。

我已经使用 DocumentListener 完成了第一部分,并将相关代码放入其 insertUpdate 方法中。

我之前没有使用过Actions,但我听说它们对于需要由多个控件触发某些东西的情况很有用。是否可以从 DocumentListener 触发操作?完全使用 Actions 是个好主意,还是应该将我的代码放在正常的方法中?

(在构造函数中):

    textAreaInput.getDocument().addDocumentListener(new DocumentListener() {
        public void insertUpdate(DocumentEvent e) {
            // do something
        }
        public void removeUpdate(DocumentEvent e) {}
        public void changedUpdate(DocumentEvent e) {}
    });

还有Action,它是一个字段:

Action doSomething = new AbstractAction("Do Something!") {
    @Override
    public void actionPerformed(ActionEvent e) {
        // do it
    }
};

澄清:

JTextArea 将接收用户粘贴的文本,我想自动解析这些文本。解析依赖于 GUI 中其他地方设置的其他值;如果用户更改了这些其他值,他可能想要重新解析文本,因此需要通过按下按钮来执行相同的操作。

【问题讨论】:

    标签: java swing action jtextcomponent documentlistener


    【解决方案1】:

    我希望用户更新 JTextArea 的内容或通过按下 JButton 手动触发某些内容。

    这对我来说没有意义。

    为什么单击按钮会调用与用户在文本区域中输入文本相同的操作?

    我以前没有使用过动作,但我听说它们对于需要由多个控件触发某些东西的情况很有用

    该语句适用于用户单击的控件,例如 JMenuItems、JButtons 或在文本字段上按 Enter。通常,当您使用 ActionListner 时可以使用它们。

    DocumentListener 不是 ActionListener,所以正如我之前所说,使用 Action 似乎不合适。

    我认为你需要澄清你的要求。

    编辑,基于澄清

    如果用户更改了这些其他值,他可能想要重新解析文本

    为什么用户可以选择?如果您更改文本区域的字体、文本、前景、背景,自动重绘的组件,您不必要求这样做。如果您查看这些方法的代码,它们总是最终会调用 revalidate() 和 repaint() 方法。

    解析取决于在 GUI 其他地方设置的其他值;

    听起来您需要一个自定义类。也许是 ParsedTextArea 或 ParsedDocument。此类将包含可以在 GUI 的其他地方设置的“属性”。它将实现 DocumentListener。它还将支持您的“parseTheText”方法。因此,每当更改属性或生成 DocumentEvent 时,您都会自动调用“parseTheText”方法。这样您就不需要单独的按钮,并且组件将始终保持同步,因为解析是自动的。

    【讨论】:

    • 我在上面的要求中添加了一些说明。我可能误解了 Actions 的用途,所以也许你是对的,但它们在这里不合适。
    • 漂亮的大纲 :-) 只挑剔 - 除了自定义类很可能不会实现 DocumentListener(但使用一个)或扩展 Document/TextComponent
    • 有趣的想法:JTextArea 的子类化。在这种特殊情况下,我有点不愿意这样做,因为 a)它增加了复杂性,b)我认为从 OO 的角度来看,将 DocumentListener 放在 Controller 类中与 JTextArea (视图)分开是有意义的,并且由于输出文本不是单独的输入函数,因此它属于单独的模型类(然后显示在单独的文本区域中)。此外,解析可能是一项昂贵的操作,因此我想将其延迟到用户完成所有设置更改为止。
    【解决方案2】:

    您可以调用actionPerformed() 方法,无论它是否在Action 中。有一个例子here

    【讨论】:

    • Action 的好处通常超过了轻微的边际开销,如 here 所述。
    • 您的意思是在 insertUpdate 方法中添加类似doSomething.actionPerformed(new ActionEvent(???)) 的内容?
    • 是的;但是,正如@camickr 所说,您必须决定这样做是否有意义。为什么不只是调用一个常用方法?
    • 我在看 Java 教程,它说“一个动作可用于将功能和状态与组件分开。例如,如果您有两个或多个执行相同功能的组件,请考虑使用 Action 对象来实现该功能。”。我有两个组件需要实现相同的功能,所以“为什么不调用通用方法”是我要问的一件事!
    • +1,在这种情况下,一个方法可能比一个动作更好。
    【解决方案3】:

    我认为您不需要创建 Action 对象。您可以将ActionListener 添加到按钮,就像您将 DocumentListener 添加到输入的文档一样。如果我正确理解您的问题,您可能应该这样做:

    textInput.getDocument().addDocumentListener(new DocumentListener(){             
        @Override
        public void insertUpdate(DocumentEvent e) {
            doIt();
        }               
        @Override
        public void removeUpdate(DocumentEvent e) {}                
        @Override
        public void changedUpdate(DocumentEvent e) {}
    });
    
    button.addActionListener(new ActionListener(){
        @Override
        public void actionPerformed(ActionEvent e) {
            doIt();
        }
    });
    

    doIt() 是一种让你可以做你想做的事的方法。

    【讨论】:

    • 期待一些专家在我的帖子中添加一些建议。
    • 你得到了你想要的 :-) -1 支持 ActionListener 而不是 Action(规则是:始终使用可用的最高抽象)+1 用于通用方法
    • @kleopatra:谢谢。我实际上从未使用过Action。我访问了你的个人资料,我同意我得到了我所要求的:)。
    猜你喜欢
    • 1970-01-01
    • 2013-04-28
    • 1970-01-01
    • 2014-12-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-06-10
    • 2016-10-18
    相关资源
    最近更新 更多