[英]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侦听器的两个方法: addMouseMotionListener和removeMouseMotionListener
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.