我正在研究Java Swing和 Adapters 来处理事件,但我对我正在研究的以下工作示例有一些疑问:
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 监听器的两种方法: addMouseMotionListener 和 removeMouseMotionListener < / p>
这是对的吗?
我还有另一个疑问:在我看来,这种编码风格很糟糕(但也许只是我的印象,因为我不知道),因为它只在一个类中完成,我可以将它分开更好的方法?
TNX
安德烈
答案 0 :(得分: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
是很尴尬的。没有其他外部类需要知道您的演示可以捕获鼠标事件,所以它应该隐藏在它的实现中。
答案 1 :(得分: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
。
关于你关于分离的问题:你应该/可以将主要方法移到单独的“主”类中。