1

イベントを処理するためにJava Swingとアダプターを研究していますが、研究している次の実際の例に関連していくつかの疑問があります。

import java.awt.*;
import java.awt.event.*;

import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.border.TitledBorder;

public class ListenerDemo extends JPanel implements MouseMotionListener{

    // Label che visualizzano la posizione X ed Y del cursore:
    JLabel labelX;
    JLabel labelY;

    public ListenerDemo() {

        /* Add a MouseMotionListener to this object to catch when the user uses the mouse: */
        addMouseMotionListener(this);

        Font f = new Font(Font.SANS_SERIF, Font.PLAIN, 50);

        TitledBorder borderX = new TitledBorder("Mouse X");
        TitledBorder borderY = new TitledBorder("Mouse Y");

        borderX.setTitleJustification(TitledBorder.CENTER);
        borderY.setTitleJustification(TitledBorder.CENTER);

        labelX = new JLabel("0");
        labelX.setBorder(borderX);
        labelY = new JLabel("0");
        labelY.setBorder(borderY);

        labelX.setFont(f);
        labelY.setFont(f);
        super.add(labelX);
        super.add(labelY);

    }

    // NOT IMPLEMENTED:
    public void mouseDragged(MouseEvent e) {}

    // IMPLEMENTED:
    public void mouseMoved(MouseEvent e) {
         labelX.setText("X : "+e.getX());
         labelY.setText("Y : "+e.getY());
    }


    public static void main(String [] argv) {

        // WindowsAdapter che implementa solo il metodo WindowClosing()
        WindowAdapter adpt = new WindowAdapter() {
            /*
             * Alla chiusura della finestra ripassa il focus al frame principale.
             * @param A low-level event that indicates that a window has changed its status
             */
            public void windowClosing(WindowEvent e) {
                System.exit(0);
            }
        };

        JFrame frame = new JFrame("ListenerDemo");  // Frame esterno

        // Add at the frame ONLY the anonymous adapter WindowAdapter class:
        frame.addWindowListener(adpt);

        // Add to the ContentPane inside the frame the ListenerDemo listener:
        frame.getContentPane().add(new ListenerDemo(), null);

        // Display the window:
        frame.pack();
        frame.setVisible(true);
        frame.setExtendedState(JFrame.MAXIMIZED_BOTH);
    }
}

このプログラムのロジックを理解するのにいくつかの困難があります。

最初の疑問は、なぜ **ListenerDemoクラスが JPanel を拡張し、MouseMotionListenerを実装するのかということです。

プログラムのロジックは次のようなものだと思います。

main()メソッド内で、 WindowAdapterのインスタンスである新しいWindowAdapterオブジェクトを作成します。これにより、 WindowEventイベントに関連するイベントを処理するいくつかのメソッドのみを実装できます。したがって、このアダプターを使用すると、興味のないリスナー メソッドの実装を回避できます。この場合、WindowAdapter はウィンドウのクローズに関連するメソッドのみを実装し、他のウィンドウ イベントは実装しません。

この推論は正しいですか?

例に従うと、特定のリスナーに関連するすべてのイベントを処理するすべてのメソッドを実装する必要がある従来のリスナーを使用するという概念との違いが示されます。

この例では、私の main()で、フレームのコンテンツにカスタムListenerDemoを追加します。このリスナーは、次の行でaddMouseMotionListenerを現在のオブジェクトに追加すると思います。

addMouseMotionListener(this);

したがって、フレームのコンテンツでのマウスの使用に関連するすべてのイベントをキャッチするリスナーがあります。

この場合、リスナーを使用しているため、MouseMotionListenerリスナーの両方のメソッド ( addMouseMotionListenerremoveMouseMotionListener ) を実装する必要があります。

それが正しいか?

私は別の疑問を持っています: このコーディングスタイルはかなりひどいようです (しかし、私はそれを知らないので、それは私の印象だけかもしれません)。

TNX

アンドレア

4

2 に答える 2

3

これListenerDemoはグラフィカル ユーザー インターフェイスであるためJPanel、デフォルト パネルのすべてのグラフィカル プロパティを継承するように拡張されています。

ListenerDemo私の意見では、も実装するのは悪い習慣ですMouseMotionListener。アダプターパターンの誤用です。では、そのパターンとは?

要するに:ListenerDemoあなたにはいくつかのコードがあります:

labelX.setText("X : "+e.getX());
labelY.setText("Y : "+e.getY());

パネルのイベントに配線したいもの:マウスが動かされたとき。

典型的なアダプター パターンでは、これに匿名の内部クラスを使用します。

public ListenerDemo() {

    addMouseMotionListener(new MouseMotionListener() {
        // NOT IMPLEMENTED:
        public void mouseDragged(MouseEvent e) {}

        // IMPLEMENTED:
        public void mouseMoved(MouseEvent e) {
            labelX.setText("X : "+e.getX());
            labelY.setText("Y : "+e.getY());
        }
    });

    // remaining code
}

ListenerDemo効果はまったく同じですが、私の意見では、実装するのは面倒ですMouseMotionListener。他の外部クラスは、デモがマウス イベントをキャプチャできることを知る必要がないため、その実装では非表示にする必要があります。

于 2013-09-24T14:14:56.710 に答える
3

*Adapterクラスは、実装インターフェイスのすべてのメソッドに空の実装を提供する便利なスタブです。ウィンドウを閉じるイベントのみに関心がある例のように、すべてのメソッドを実装したくない場合は、それらを使用できます。

UI を実現するクラスがイベント ハンドラー インターフェイスも実装することは、非常に一般的な方法です。それは主に便利だからですが、実はスタイルが悪いのですListenerDemoリスナーは内部的にのみ必要なので、クラスのパブリック API に追加することはお勧めできません。(あなたのクラスのユーザーがどこかでそれを として使用したくないと思いMouseMotionListenerませんか?)

MouseMotionListenerしたがって、実装または派生する匿名の内部クラスを持つ方がはるかに優れていますMouseAdapter

private final MouseMotionListener mouseListener = new MouseAdapter() {
    public void mouseMoved(MouseEvent e) {
        labelX.setText("X : "+e.getX());
        labelY.setText("Y : "+e.getY());
    }
}

mouseListenerこれで、コンストラクターで の代わりに登録できますthis

分離に関する質問について: メイン メソッドを別の「メイン」クラスに移動する必要があります。

于 2013-09-24T14:15:19.990 に答える