2

私はこのコードをJavaで使用しようとしました.JFrameを独自のActionListenerとして使用しました。現在、理論的には可能です。Java では、クラスは多数のインターフェースを実装することも、別のクラス拡張することもできるからです。

import java.awt.BorderLayout;
import java.awt.EventQueue;
import java.awt.Font;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.SwingConstants;
import javax.swing.border.EmptyBorder;

/*
 * This is an example of the strangeness of the syntax of Java. In this example, I am using the JFrame itself as the listener for its component, namely a JButton which, on clicking, ends the program. 
 * Warning : This is just an example, and I would never recommend this syntax, for I do not know the full consequences yet.
 */

@SuppressWarnings("serial") public class ListenerTest extends JFrame implements ActionListener{

    private final JPanel contentPane;
    private final JLabel message;
    private final JButton button;

    /**
     * Launch the application.
     */
    public static void main(String[] args){
        EventQueue.invokeLater(new Runnable(){
            @Override public void run(){
                try{
                    ListenerTest frame = new ListenerTest();
                    frame.setVisible(true);
                } catch(Exception e){
                    e.printStackTrace();
                }
            }
        });
    }

    /**
     * Create the frame.
     */
    public ListenerTest(){
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setBounds(100, 100, 200, 150);
        contentPane = new JPanel();
        contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));
        setContentPane(contentPane);
        contentPane.setLayout(new BorderLayout(0, 0));

        message = new JLabel("Hello World");
        message.setFont(new Font("Times New Roman", Font.PLAIN, 16));
        message.setHorizontalAlignment(SwingConstants.CENTER);
        contentPane.add(message, BorderLayout.CENTER);

        button = new JButton("Click Me!");
        button.addActionListener(this);
        contentPane.add(button, BorderLayout.SOUTH);
    }

    @Override public void actionPerformed(ActionEvent arg0){
        JOptionPane.showMessageDialog(null, "Well, I listened for myself!");
        System.exit(0);
    }

}

私の質問は次のとおりです。コンポーネントを独自のリスナーとして使用することに問題はありますか?

4

2 に答える 2

5

うまくいきますか...はい。

そうは言っても。不適切なコーディング手法の例を何百と挙げることができますが、これはその 1 つです。

  • Swing でクラスを拡張する必要はほとんどありませんJxxx(おそらくカスタム ペインティングを除く)。あなたの例では、JFrameそれを拡張する代わりに使用できます
  • インターフェイスを実装するクラスを持つことActionListenerは、API/コードのユーザーに、それを として使用できることを示唆していますActionListener。ただし、クラスは として設計されていませんActionListener。それが 1 つであるという事実は、隠したほうがよい実装の詳細です。したがって、ActionListener直接実装する代わりに (匿名クラス、内部クラス、...) を使用します (または、より良い方法として、 を使用しますAction) 。

いいえ、インターフェイスを直接実装することは、GUI の読み込みに長い時間がかかることActionListenerとは関係ありません。

そして補足として。JFrame#pack()への呼び出しよりも使用することをお勧めしますsetBounds

于 2012-11-24T16:59:54.787 に答える
4

ActionListener単一のボタンのみに使用される場合、クラスにを実装する必要があるのはなぜですか?

これの副作用は次のとおりです。

  • 他のクラスとコンポーネントがこのリスナーにアクセスできるという事実に追加されます

  • どのコンポーネントがリスナーを起動しているかを特定するには、より多くのチェックが必要になります (リスナーを起動したかどうかの if チェックを使用して、他のコンポーネントの多くの再利用リスナーを見ているため)。

  • Listenerクラスがリスナーとして使用されない限り、クラスにa を実装するのはあまり良い習慣ではありません。

適切な解決策 IMO:

匿名の内部クラス リスナーを使用します。

ActionListener al=new ActionListener() {
    @Override
     public void ActionPerformed(ActionEvent ae) {
     }
};

を介してこれを単一のボタンに追加できるようになりましたaddActionListener

クラスにリスナーを実装したくないという上記の結論に達した理由は、Swing にありますJFrame。クラスを不必要に拡張しないでください。

注(特定の問題とは関係ありません):

  • @Robinが誰がドキュメントを述べたと言ったように、私自身のコーディングの好みはEventQueueむしろ使用しません: 1.3の時点で、このメソッドは単なるカバーですSwingUtilities.invokeXXXjava.awt.EventQueue.invokeLater()
于 2012-11-24T17:00:08.630 に答える