[英].class after an Interface with Custom Events in Java Swing
I'm learning about Java Swing and I have found an advanced code (in my opinion) about Swing using MVC and Observer patterns. 我正在学习Java Swing,并且发现了使用MVC和Observer模式的关于Swing的高级代码。 It is very difficult for me and I try to understand it. 这对我来说非常困难,我试图理解它。 And I have 2 questions: 我有两个问题:
What exactly does DetailListener.class? DetailListener.class到底是什么? It is the first time when I use .class after an interface. 这是我第一次在接口后使用.class。 I have tried to search on stackoverflow about ".class syntax" and I see it can be used after a class, but I still don't understand what it does in this situation. 我试图搜索有关“ .class语法”的stackoverflow,但我发现它可以在使用一个类后使用,但是我仍然不了解它在这种情况下的作用。
What exactly does the method fireDetailEvent()? 方法fireDetailEvent()到底是什么?
Thanks in advance! 提前致谢!
import javax.swing.JFrame;
import javax.swing.SwingUtilities;
public class App {
public static void main(String args[]) {
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
JFrame frame = new MainFrame("Hello world Swing");
frame.setSize(500, 400);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
}
});
}
}
MainFrame 大型机
import java.awt.BorderLayout;
import java.awt.Container;
import javax.swing.JFrame;
import javax.swing.JTextArea;
public class MainFrame extends JFrame {
private JTextArea textArea;
public MainFrame(String title) {
super(title);
Container c = getContentPane();
c.setLayout(new BorderLayout());
textArea = new JTextArea();
DetailsPanel detailsPanel = new DetailsPanel();
detailsPanel.addDetailListener(new DetailListener() {
public void detailEventOccurred(DetailEvent event) {
String text = event.getText();
textArea.append(text);
}
});
c.add(textArea, BorderLayout.CENTER);
c.add(detailsPanel, BorderLayout.WEST);
}
}
DetailsPanel DetailsPanel
import java.awt.Dimension;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.event.EventListenerList;
public class DetailsPanel extends JPanel {
private static final long serialVersionUID = -5115286206114930420L;
private EventListenerList listenerList = new EventListenerList();
public DetailsPanel() {
Dimension size = getPreferredSize();
size.width = 250;
setPreferredSize(size);
setBorder(BorderFactory.createTitledBorder("Personal details"));
JLabel nameLabel = new JLabel("Name:");
JLabel occupationLabel = new JLabel("Occupation:");
JTextField nameField = new JTextField(10);
JTextField occupationField = new JTextField(10);
JButton addBtn = new JButton("Add");
setLayout(new GridBagLayout());
GridBagConstraints gc = new GridBagConstraints();
////// First column /////
gc.anchor = GridBagConstraints.LINE_END;
gc.weightx = 0.5;
gc.weighty = 0.5;
gc.gridx = 0;
gc.gridy = 0;
add(nameLabel, gc);
gc.gridy = 1;
add(occupationLabel, gc);
////// Second column /////
gc.anchor = GridBagConstraints.LINE_START;
gc.gridx = 1;
gc.gridy = 0;
add(nameField, gc);
gc.gridy = 1;
add(occupationField, gc);
////// Final row /////
gc.anchor = GridBagConstraints.FIRST_LINE_START;
gc.weightx = 10;
gc.weighty = 10;
gc.gridy = 2;
add(addBtn, gc);
addBtn.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
String name = nameField.getText();
String occupation = occupationField.getText();
String text = name + ": " + occupation + "\n";
System.out.println(text);
fireDetailEvent(new DetailEvent(this, text));
}
});
}
public void fireDetailEvent(DetailEvent event) {
Object[] listeners = listenerList.getListenerList();
for (int i = 0; i < listeners.length; i += 2) {
if (listeners[i] == DetailListener.class) {
((DetailListener)listeners[i+1]).detailEventOccurred(event);
}
}
}
public void addDetailListener(DetailListener listener) {
listenerList.add(DetailListener.class, listener);
}
public void removeDetailListener(DetailListener listener) {
listenerList.remove(DetailListener.class, listener);
}
}
DetailListener DetailListener
import java.util.EventListener;
public interface DetailListener extends EventListener {
public void detailEventOccurred(DetailEvent event);
}
DetailEvent DetailEvent
import java.util.EventObject;
public class DetailEvent extends EventObject {
private String text;
public DetailEvent(Object source, String text) {
super(source);
this.text = text;
}
public String getText() {
return text;
}
}
1) What exactly does DetailListener.class? 1)DetailListener.class到底是什么?
Instances of the class Class represent classes and interfaces in a running Java application. 类Class的实例表示正在运行的Java应用程序中的类和接口。
This is somewhat confusing so let's look at a an example. 这有点令人困惑,所以让我们看一个例子。 Calling DetailListener.class provides its Class representation. 调用DetailListener.class提供其Class表示形式。 In this specific case DetailListener.class
provides a Class<DetailListener>
so it's possible to do this: 在这种特定情况下, DetailListener.class
提供了一个Class<DetailListener>
因此可以执行以下操作:
Class<DetailListener> cdl = DetailListener.class;
cdl
is just another variable similar to how frame
is just another variable. cdl
只是另一个变量,类似于frame
只是另一个变量。 frame
happens to be a JFrame
which provides some methods, while cdl
is a Class<DetailListener>
which provides a different set of methods. frame
恰好是提供某些方法的JFrame
,而cdl
是提供不同方法集的Class<DetailListener>
。
cdl
's type is a Class<DetailListener>
which represents the DetailListener
class. cdl
的类型是Class<DetailListener>
,它表示DetailListener
类。
but I still don't understand what it does in this situation 但我仍然不明白在这种情况下它会做什么
Consider this code: 考虑以下代码:
listenerList.add(DetailListener.class, listener);
listenerList
is of type EventListenerList
. listenerList
的类型为EventListenerList
。 According to its API , the add(...)
method parameters require a Class and a T instance. 根据其API , add(...)
方法参数需要一个Class和一个T实例。 In this case, the generic T is DetailListener. 在这种情况下,通用T为DetailListener。 So far the listener has been registered but it leads into your next question. 到目前为止,听众已经注册,但是它会引出您的下一个问题。
#2 What exactly does the method fireDetailEvent()? #2 fireDetailEvent()方法到底是什么?
When the listener was registered the listenerList
keeps an internal array which can be referenced later. 注册listenerList
器后, listenerList
会保留一个内部数组,以后可以引用该数组。 The array holds both the Class and the actual listener instance. 该数组同时包含Class和实际的侦听器实例。 So invoking 如此调用
Object[] listeners = listenerList.getListenerList();
provides access to the array. 提供对阵列的访问。 In this case: 在这种情况下:
listeners[0] = DetailListener.class
listeners[1] = reference to the anonymous inner class instance created from detailsPanel.addDetailListener(...)
So the loop in fireDetailEvent(...)
is guaranteed to be a multiple of 2 (0 also works if there are no registered listeners). 因此, fireDetailEvent(...)
的循环保证为2的倍数(如果没有注册的侦听器,则0也适用)。 But listenerList
could hold any type of listener, so 但是listenerList
可以容纳任何类型的侦听器,因此
if (listeners[i] == DetailListener.class) {
uses the Class to check for equality to make sure it's safe to caste to be able to pass the DetailEvent
to the listener (which is the next element in the array). 使用Class检查是否相等,以确保能够安全地进行等级传递,以便能够将DetailEvent
传递给侦听器(这是数组中的下一个元素)。 Using ==
(instead of .equals()
) is okay in this context since DetailListener.class always provides the same Class. 在这种情况下,可以使用==
(而不是.equals()
),因为DetailListener.class始终提供相同的Class。
What exactly does
DetailListener.class
?DetailListener.class
到底是DetailListener.class
?
DetailListener.class
is a so-called class literal. DetailListener.class
是所谓的类文字。 Basically, it is a constant of type Class
referring to the DetailListener
type. 基本上,它是Class
类型的常量,表示DetailListener
类型。
You can find more and better explanations about this at What is a class literal in Java? 您可以在Java什么是类文字中找到更多更好的解释。 and its answers. 及其答案。
What exactly does the method
fireDetailEvent()
? 方法fireDetailEvent()
到底是什么?
Your DetailsPanel
class uses an EventListenerList
for handling event listeners and sending events to them. 您的DetailsPanel
类使用EventListenerList
来处理事件侦听器并将事件发送给他们。
The comment given in class EventListenerList gives a detailed description how to use it. 类EventListenerList中给出的注释详细说明了如何使用它。 Read this description and you will recognize, that the methods addDetailListener
, removeDetailListener
and fireDetailEvent
of your class DetailsPanel
are written exactly following this description. 仔细阅读本说明,你会认识到,这些方法addDetailListener
, removeDetailListener
和fireDetailEvent
类的DetailsPanel
写这正好说明如下。
The method fireDetailEvent
fires a DetailEvent
to all those listeners which have registered themselves earlier by addDetailListener
. 该方法fireDetailEvent
触发一个DetailEvent
所有那些已经由早期注册自己的听众addDetailListener
。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.