3

我有一个简单的 GUI,其中包含:

  • 一个按钮。
  • 两个单选按钮

现在我想听听这些按钮中的每一个。我所做的是这样的:

public class TestApp implements ActionListener {

    private JFrame frame;
    private JButton btn;
    private JRadioButton rdb1;
    private JRadioButton rdb2; 

    public static void main(String[] args) { /*....*/ }

    private void initialize() {
       //Each time I add a button, I add it to the listener:
       btn = new JButton("Button");
       btn.addActionListener(this);
       //..
       rdb1 = new JRadioButton("Value1");
       rdb1.addActionListener(this);
       //And so on...
    }

    //The ActionEvents  
    public void actionPerformed(ActionEvent e) {
       if(e.getSource()==btn)
       //...
       if(e.getSource()==rdb1)
       //...        
    }
}

现在我想知道这是否被认为是一种好/坏的风格?

4

5 回答 5

5

除非监听器是一个很长的方法,否则我个人更喜欢匿名类模式:

        final JButton btn = new JButton("Button");
        final JRadioButton rdb1 = new JRadioButton("Value1");
        final ActionListener listener = new ActionListener() {
            @Override
            public void actionPerformed(final ActionEvent e) {
                if (e.getSource() == btn) {
                    //...
                } else if (e.getSource() == rdb1) {
                    //...        
                }
            }
        };
        btn.addActionListener(listener);
        rdb1.addActionListener(listener);

甚至更好:

    btn.addActionListener(new ActionListener (){
         public void actionPerformed(ActionEvent e) {      
             // btn handling code
             }
    });
    rdb1.addActionListener(new ActionListener (){
         public void actionPerformed(ActionEvent e) {      
             // rdb1 handling code
             }
    });

您正在使用的模式允许其他类将类 TestApp 设置为其他类的侦听器 - 除非这是故意的,否则这不是一个好习惯。

于 2012-11-09T23:52:48.680 回答
4

很大程度上归结为动作侦听器试图做的事情的复杂性。如果您想要小型的一次性操作,那么匿名类将适合。

使用这种监听器风格的主要好处是它可以准确地隔离动作正在做什么以及它正在为谁做。缺点是当监听器包含超过 10 行或更多行时,因为它开始变得难以阅读并知道监听器实际结束的位置。

在这种情况下,像内部类这样的东西可能更合适。它具有匿名类的好处(与使用它的类相关联),但更易于阅读。

如果您想要可重用的操作(想想诸如打开、新建、保存之类的事情),那么您最好使用Action API,它提供了自我可配置性以及自包含的操作侦听器

恕我直言

于 2012-11-10T00:33:03.690 回答
3

更面向对象的方式是创建一个匿名类来执行每个监听器。

只创建一个开启事件源组件的监听器可读性不强,而且当监听器数量增加时,容易出错。您很容易忘记在 switch 块(或 if-else 块链)中处理所有可能的事件源,这将导致运行时异常静默错误行为(这种情况不会发生任何事情)。

为每个组件添加单独的侦听器将使您在编译时检查您是否忘记处理所有这些侦听器。

public class TestApp {

    // you can initialize fields inline to make thing shorter and safer
    private JButton btn = new JButton("Button");
    private JRadioButton rdb1 = new JRadioButton("Value1");

    private void initialize() {
        btn.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                // something
            }
        });
        rdb1.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                // something else
            }
        });
    }
}

因为匿名类语法非常冗长,您可以通过将侦听器移动到私有字段来缩短初始化方法的代码。

public class TestApp {

    private JButton btn = new JButton("Button");
    private JRadioButton rdb1 = new JRadioButton("Value1");

    private void initialize() {
        btn.addActionListener(btnListener);
        rdb1.addActionListener(rb1Listener);
    }

    private final ActionListener btnListener = new ActionListener() {
        @Override
        public void actionPerformed(ActionEvent e) {
            // something
        }
    };

    private final ActionListener rb1Listener = new ActionListener() {
        @Override
        public void actionPerformed(ActionEvent e) {
            // something else
        }
    };
}
于 2012-11-10T00:02:59.473 回答
2

你可以考虑另外两个想法:

  1. 为每个 UI 元素提供自己的 Listener;这样他们就完全独立了。
  2. 将侦听器注入到您的 Swing UI 中,而不是调用 new。你让用户有机会改变他们认为合适的行为。让您的 Swing UI 做它应该做的事情:显示结果。而已。我认为侦听器是控制器逻辑的一部分。
于 2012-11-09T23:47:16.107 回答
2

这在一定程度上取决于你想在actionPerformed方法中做什么。如果没有其他类可能想要调用此方法,那么我可能会想actionPerformed通过创建内部类来缩小方法的范围,例如:-

public class TestApp {

    private JFrame frame;
    private JButton btn;
    private JRadioButton rdb1;
    private JRadioButton rdb2; 

    private class CombinedActionListener implements ActionListener {
         public void actionPerformed(ActionEvent e) {
             if(e.getSource()==btn)
             //...
             if(e.getSource()==rdb1)
             //...        
             }
    }

    public static void main(String[] args) { /*....*/ }

    private void initialize() {
       ActionListener listener = new CombinedActionListener()

       //Each time I add a button, I add it to the listener:
       btn = new JButton("Button");
       btn.addActionListener(listener);
       //..
       rdb1 = new JRadioButton("Value1");
       rdb1.addActionListener(listener);
       //And so on...
    }
}

您甚至可以通过将按钮实例传递给构造函数来使侦听器类成为静态内部类或顶级类 - 这将使侦听器类更易于测试。

正如我上面所说,这在很大程度上取决于 i) 是否有其他人可能调用此方法,以及 ii) 方法内部逻辑的复杂性。

于 2012-11-09T23:49:06.623 回答