简体   繁体   English

有关在Java Swing中使用适配器和侦听器的一些疑问

[英]Some doubts about the use of adapter and listener in Java Swing

I am studying Java Swing and the Adapters to handle events but I have some doubts related to the following working example that I am studying: 我正在研究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);
    }
}

I have some difficulties to understand the logic of this program: 我很难理解该程序的逻辑:

The first doubt is Why the **ListenerDemo class extendes JPanel and implements MouseMotionListener ? 第一个疑问是为什么** ListenerDemo类扩展JPanel并实现MouseMotionListener

I think that the logic of the program is the following one: 我认为该程序的逻辑如下:

Inside the main() method I create a new WindowAdapter object that is an instance of the WindowAdapter that allows me to implement only some methods that handle events related to my WindowEvent events. 里面的main()方法创建一个新的WindowAdapter的对象,它是WindowAdapter的实例,让我只执行一些方法来处理与我的WindowEvent事件的事件。 So, using this adapter, I can avoid implementing some listener methods that do not interest me. 因此,使用此适配器,我可以避免实现一些我不感兴趣的侦听器方法。 In this case the WindowAdapter implement only the moethod related to the closoure of a window and not implement others windows events. 在这种情况下,WindowAdapter仅实现与窗口结束有关的方法,而没有实现其他Windows事件。

Is this reasoning correct? 这个推理正确吗?

Following the example shows the difference with the concept of using the classic listener in which I have to implement all the method that handle all the events related to a specific listener. 以下示例显示了与使用经典侦听器的概念的区别,其中我必须实现处理与特定侦听器有关的所有事件的所有方法。

In this example, in my main(), I add a custom ListenerDemo to the content of the frame and I think that this listener add a addMouseMotionListener to the current object by this line: 在此示例中,在我的main()中,我向框架的内容添加了一个自定义ListenerDemo ,并且我认为此侦听器通过此行向当前对象添加了addMouseMotionListener

addMouseMotionListener(this);

So I have a listener that catch all the events related to the use of the mouse in the content of my frame. 因此,我有一个侦听器,可在框架内容中捕获与鼠标使用相关的所有事件。

In this case, because I am using listener, I have to implement both the methods of the MouseMotionListener listener: addMouseMotionListener and removeMouseMotionListener 在这种情况下,因为我正在使用侦听器,所以我必须实现MouseMotionListener侦听器的两个方法: addMouseMotionListenerremoveMouseMotionListener

Is it correct? 这是正确的吗?

I have another doubt: it seems to me that this coding style is pretti orrible (but maybe it is only my impression because I don't know it) because it do all in a single class, can I separate it in a better way? 我还有一个疑问:在我看来,这种编码风格太糟糕了(但也许只是我的印象,因为我不知道),因为它在单个类中完成所有工作,我可以用更好的方法将其分开吗?

Tnx 特纳克斯

Andrea 安德里亚

Your ListenerDemo is a graphical user interface, so that's why it extends JPanel : that way it inherits all graphical properties of a default panel. 您的ListenerDemo是一个图形用户界面,所以这就是它扩展JPanel的原因:这样,它继承了默认面板的所有图形属性。

In my opinion, it is bad practice that ListenerDemo also implements MouseMotionListener . 在我看来, ListenerDemo还实现MouseMotionListener是一种不好的做法。 It is a misuse of the adapter pattern. 这是对适配器模式的滥用。 So what is that pattern? 那是什么模式?

In short: in ListenerDemo you have some code: 简而言之:在ListenerDemo您有一些代码:

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

which you want to wire to an event of the panel: when the mouse is moved. 您想连接到面板事件的对象:移动鼠标时。

The typical adapter pattern uses an anonymous inner class for this: 典型的适配器模式为此使用匿名内部类:

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
}

The effect is the very same, but in my opinion it is awkward to make ListenerDemo implement MouseMotionListener . 效果是一样的,但是在我看来,使ListenerDemo实现MouseMotionListener是很尴尬的。 No other external class needs to know that your demo can capture mouse events, so it should be hidden in its implementation. 没有其他外部类需要知道您的演示可以捕获鼠标事件,因此应将其隐藏在其实现中。

The *Adapter classes are just helpful stubs that provide empty implementations for every method of the implementing interface. *Adapter类只是有用的存根,它们为实现接口的每种方法提供空的实现。 You can use them, if you do not want to implement all methods - like in your example where you're only interested in the window-closing event. 如果您不希望实现所有方法,则可以使用它们,例如在您仅对窗口关闭事件感兴趣的示例中。

It is a very common practice that the class that realizes your UI also implements the event handler interface(s). 实现您的UI的类还实现事件处理程序接口是一种非常普遍的做法。 That's mainly because it's convenient, but in fact it's bad style ! 这主要是因为它很方便,但是实际上这是不好的风格 Your ListenerDemo needs the listener only internally, so it is not a good idea to add it to the public API of the class. 您的ListenerDemo仅在内部需要侦听ListenerDemo ,因此将其添加到类的公共API中不是一个好主意。 (You don't want users of your class to use it somewhere as a MouseMotionListener , do you?) (您不希望您班级的用户将它用作MouseMotionListener ,在吗?)

So it's much better to have a anonymous inner class that either implements MouseMotionListener or derives from MouseAdapter : 因此,最好有一个匿名内部类来实现MouseMotionListener或从MouseAdapter派生:

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

Now, in the constructor you can register mouseListener instead of this . 现在,在构造函数中,您可以注册mouseListener而不是this

Concerning your question about separation: You should/could move the main method out into a separate 'Main' class. 关于分离的问题:您应该/可以将main方法移到单独的“ Main”类中。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 有关简单的Swing侦听器代码的一些疑问 - Some doubts about a simple Swing listener code 关于Java SWING和Swing应用程序框架的一些疑问 - Some doubts about Java SWING and Swing Application Framework 关于Java语法的一些疑问 - Some Doubts about Java Syntax 有关将适配器模式应用于Java中的Swing事件的一些说明 - Some clarifications about Adapter pattern applied to Swing events in Java 与在Java Swing程序中使用SwingUtilities.invokeLater()方法有关的一些疑问 - Some doubts related to the use of the SwingUtilities.invokeLater() method in Java Swing program 关于如何实现Swing Listener的一些问题 - Some questions about how implement a Swing Listener 关于Spring Application Context的Java配置(依赖注入)的一些疑问 - Some doubts about Java Configuration of the Spring Application Context (dependency injection) 有关将Java多态性应用于Calendar和GregoriaCalendar案例的一些疑问 - Some doubts about Java polymorphism applied to the Calendar and GregoriaCalendar case Java对ActionEvent的疑惑 - Java doubts about ActionEvent 关于在Spring Framework中使用** @Autowired **注释和接口声明的一些疑问 - Some doubts about the use of **@Autowired** annotation and interface declaration in Spring Framework
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM