Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/328.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
关于在JavaSwing中使用适配器和侦听器的一些疑问_Java_Swing_Listener_Adapter - Fatal编程技术网

关于在JavaSwing中使用适配器和侦听器的一些疑问

关于在JavaSwing中使用适配器和侦听器的一些疑问,java,swing,listener,adapter,Java,Swing,Listener,Adapter,我正在学习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 JP

我正在学习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只实现与窗口资源相关的方法,而不实现其他windows事件

这个推理正确吗

下面的示例显示了与使用classic listener概念的区别,在classic listener中,我必须实现处理与特定listener相关的所有事件的所有方法

在本例中,在my main()中,我向框架内容添加了一个自定义的ListenerDemo,我认为此侦听器通过以下行向当前对象添加了一个addMouseMotionListener

addMouseMotionListener(this);
因此,我有一个监听器,它可以在我的框架内容中捕获与鼠标使用相关的所有事件

在这种情况下,因为我使用的是listener,所以我必须实现MouseMotionListenerlistener的两种方法:addMouseMotionListenerremoveMouseMotionListener

对吗

我还有另一个疑问:在我看来,这种编码风格很可爱(但也许这只是我的印象,因为我不知道它),因为它在一个类中完成所有工作,我能以更好的方式将其分离吗

Tnx


Andrea

您的
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
是很尴尬的。没有其他外部类需要知道您的演示可以捕获鼠标事件,因此它应该隐藏在其实现中。

您的
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
是很尴尬的。没有其他外部类需要知道您的演示可以捕获鼠标事件,因此它应该隐藏在其实现中。

适配器类只是有用的存根,为实现接口的每个方法提供空实现。如果您不想实现所有方法,您可以使用它们——比如在您的示例中,您只对窗口关闭事件感兴趣

实现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


关于您关于分离的问题:您应该/可以将main方法移出到一个单独的“main”类中。

适配器类只是有用的存根,为实现接口的每个方法提供空实现。如果您不想实现所有方法,您可以使用它们——比如在您的示例中,您只对窗口关闭事件感兴趣

实现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

关于你关于分离的问题:你应该/可以移动主要方法