使用DocumentListener与Actions

7
我正在开发一个应用程序,希望能够通过用户更新JTextArea的内容或手动按下JButton来触发某些操作。
我已经使用DocumentListener并将相关代码放在其insertUpdate方法中完成了第一部分。
虽然我之前没有使用过Action类,但我听说它们在需要多个控件触发操作的情况下非常有用。可以从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中其他设置的值;如果用户更改了这些其他值,则可能希望重新解析文本,因此需要按下按钮执行相同的操作。

3个回答

4
我希望当用户更新JTextArea的内容或通过按下JButton手动更新时,都能触发某些操作。
这对我来说没有意义。为什么点击按钮会调用与用户在文本区域中输入文本相同的操作?
我以前没有使用过Actions,但我听说它们在需要多个控件触发某些操作的情况下很有用。
该语句适用于用户单击的控件,例如JMenuItems、JButtons或在文本字段上按Enter。一般来说,当您使用ActionListner时,它们可以被使用。
DocumentListener不是ActionListener,因此如我之前所述,使用Action似乎不合适。我认为您需要澄清您的要求。
根据澄清后的说明进行编辑,如果用户更改其他值,他可能需要重新解析文本。
为什么用户有选择权?如果您更改文本区域的字体、文本、前景色、背景色,组件会自动重新绘制,您不必请求这样做。如果您查看这些方法的代码,它们始终最终调用revalidate()和repaint()方法。
解析取决于GUI其他地方设置的其他值;
听起来像是您需要一个自定义类。也许是ParsedTextArea或ParsedDocument。该类将包含可在GUI中其他位置设置的"属性"。它将实现DocumentListener。它还将支持您的"parseTheText"方法。因此,每当属性更改或生成DocumentEvent时,您将自动调用"parseTheText"方法。这样,您就不需要单独的按钮,并且组件始终保持同步,因为解析是自动的。

我已经在上面对我的要求进行了一些澄清。也许我误解了Actions的用途,所以也许你是正确的,它们在这里不合适。 - Luigi Plinge
不错的大纲 :-) 只是挑剔一点 - 除了很可能自定义类不会 实现 DocumentListener(而是使用它),也不会扩展Document/TextComponent。 - kleopatra
有趣的想法关于JTextArea的子类化。在这种特定情况下,我有点不愿意这样做,因为a)它增加了复杂性,b)从面向对象的角度来看,我认为将DocumentListener放在与JTextArea(视图)分开的Controller类中是有意义的,而且由于输出文本不仅仅是输入的函数,所以它属于一个单独的模型类(然后显示在一个单独的文本区域中)。此外,解析可能是一项昂贵的操作,因此我希望将其延迟到用户进行所有设置更改之后。 - Luigi Plinge

3
您可以调用actionPerformed()方法,无论它是否在Action中。这里有一个例子,点击此处查看。

通常情况下,Action的好处要大于轻微的边际开销,正如这里所提到的。 - trashgod
дҪ зҡ„ж„ҸжҖқжҳҜеңЁinsertUpdateж–№жі•дёӯж·»еҠ зұ»дјјдәҺdoSomething.actionPerformed(new ActionEvent(???))иҝҷж ·зҡ„еҶ…е®№еҗ—пјҹ - Luigi Plinge
是的,但正如@camickr所指出的那样,您必须决定是否有意义这样做。为什么不只调用一个通用方法呢? - trashgod
我正在查看Java教程,其中提到“操作可以用于将功能和状态与组件分离。例如,如果您有两个或更多执行相同功能的组件,请考虑使用Action对象来实现该功能。” 我有两个需要实现相同功能的组件,所以“为什么不调用一个公共方法”是我要问的一件事! - Luigi Plinge
+1,针对这种情况,方法可能比Action更好。 - camickr
жҳҜзҡ„пјҢActionдёәжӮЁжҸҗдҫӣдәҶдёҖз§Қе“Қеә”ActionEventзҡ„еёёи§Ғж–№жі•пјҢдҪҶжӯЈеҰӮcamickrе’ҢkleopatraжүҖе»әи®®зҡ„йӮЈж ·пјҢеұһжҖ§з»ҙжҠӨжңҖеҘҪз”ұе…¶еӨ„зҗҶгҖӮ - trashgod

2
我认为您无需创建Action对象。您可以像将DocumentListener添加到输入文档一样,将ActionListener添加到按钮上。如果我正确理解了您的问题,或许您应该像这样做:
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()" 是一个方法,你可以在其中做你想做的事情。"

期望一些专家能够在我的帖子中添加一些建议。 - Mohayemin
你得到了你所要求的内容:-1 倾向于使用 ActionListener 而不是 Action(规则是:始终使用最高抽象级别)+1 通用方法。 - kleopatra
@kleopatra:谢谢。我实际上从未使用过Action。我访问了你的个人资料,我同意我得到了我所要求的:)。 - Mohayemin

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接