我的问题在于无法听清我的课程之一。
该软件是一个基于Java swing的桌面应用程序,其中JFrame的子类MainFrame正在侦听多个对话框。所有对话框窗口都是我的PDialog类的子级,其中包含与侦听器相关的变量和函数。这是PDialog类的样子:
public class PDialog extends JDialog {
private MainFrameChildrenListener listener;
// Function that assigns its parameter to local listener value "listener setter"
public void addMainFrameChildrenListener(MainFrameChildrenListener listener) {
this.listener = listener;
}
public void removeMainFrameChildrenListener() {
this.listener = null;
}
public void firePDialogEvent(MainFrameChildrenEventObject event) {
this.listener.dialogEventOccured(event);
}
// This method was useful when I tried to debug with System.out.println() method
public String retrieveListenerInformation(){
if(listener == null){
return "No listener loaded";
}
return this.listener.toString();
}
}
因此,我创建了3个对话框,使用它们作为PDialog的子类继承的函数可以成功收听。 MainFrame类实现MainFrameChildrenListener侦听器对象,并将其作为侦听器传递到其构造函数中的对话框:
public class MainFrame extends JFrame implements MainFrameChildrenListener {
private PDialogCustomer dialogCustomer = new PDialogCustomer();
private PDialogOrder dialogOrder = new PDialogOrder();
private PDialogProduct dialogProduct = new PDialogProduct();
private PDialogMaterial dialogMaterial = new PDialogMaterial();
public MainFrame(){
dialogMaterial.addMainFrameChildrenListener(this);
dialogCustomer.addMainFrameChildrenListener(this);
dialogOrder.addMainFrameChildrenListener(this);
dialogProduct.addMainFrameChildrenListener(this);
System.out.println("Material dialog: " + dialogMaterial.retrieveListenerInformation());
System.out.println("Customer dialog: " + dialogCustomer.retrieveListenerInformation());
System.out.println("Order dialog: " + dialogOrder.retrieveListenerInformation());
System.out.println("Product dialog: " + dialogProduct.retrieveListenerInformation());
}
令人惊讶的是,启动应用程序后,控制台将输出PDialog.retrieveListenerInformation()指令,其外观如下所示:
Material dialog: No listener loaded
Customer dialog: view.MainFrame[-deleted the .toString() rubbish to keep things short-]
Order dialog: view.MainFrame[-deleted the .toString() rubbish to keep things short-]
Product dialog: view.MainFrame[-deleted the .toString() rubbish to keep things short-]
而且,如果我尝试触发侦听器事件,则会为PDialog.firePDialogEvent()方法获取空指针异常。
我试图通过其构造函数将侦听器传递给PDialogMaterial类,甚至尝试仅在PDialogMaterial类内创建新方法来传递侦听器,而且没有运气。我能够使事情工作的唯一方法是创建一个新的MainFrameChildrenListener变量,该变量被声明为public(eek!),并从MainFrame构造函数直接访问它(eeeeek!),如下所示:
public class PDialogMaterial extends PDialog{
public MainFrameChildrenListener testListener;
}
public class MainFrame extends JFrame implements MainFrameChildrenListener{
public MainFrame(){
dialogMaterial.testListener = this;
dialogCustomer.addMainFrameChildrenListener(this);
dialogOrder.addMainFrameChildrenListener(this);
dialogProduct.addMainFrameChildrenListener(this);
}
}
关于为什么所有继承的相同侦听器处理方法的4个类中有3个行为与第四个类不同的原因,是否有任何解释?我可能会缺少什么?
评论跟进:
PDialogMaterial的完整代码(不起作用):
package view.dialogs;
import java.awt.Dimension;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.net.URL;
import javax.swing.DefaultComboBoxModel;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JTextField;
import view.listeners.MainFrameChildrenEventObject;
import view.listeners.MainFrameChildrenListener;
import view.utils.DoubleFormatCheck;
public class PDialogMaterial extends PDialog {
private static final long serialVersionUID = 6190469565649183032L;
// private PMaterialFabricObject fabricObject;
public static final int FABRIC_MASK = 0;
public static final int STRAP_MASK = 1;
public static final int PARTS_MASK = 2;
public static final int THREAD_MASK = 3;
private String[] fabricMaterialList = { "Cotton", "Brocate", "Satin", "Synthetic" };
private String[] fabricColorsList = { "Red", "Green", "Blue", "Purple", "Gray", "Yellow", "Black", "Khakhi",
"Carcaline" };
private MainFrameChildrenListener listener;
private GridBagConstraints gc = new GridBagConstraints();
private Dimension size = new Dimension(300, 300);
private DoubleFormatCheck dfc = new DoubleFormatCheck();
private JTextField nameField = new JTextField(8);
private JTextField priceField = new JTextField(6);
private JTextField widthField = new JTextField(6);
private JTextField vendorField = new JTextField(8);
private JButton okButton = new JButton("Ok");
private JButton cancelButton = new JButton("Cancel");
private DefaultComboBoxModel<String> fabricMaterialComboBoxModel = new DefaultComboBoxModel<String>(
fabricMaterialList);
private DefaultComboBoxModel<String> materialColorComboBoxModel = new DefaultComboBoxModel<String>(
fabricColorsList);
private JComboBox<String> fabricMaterialComboBox = new JComboBox<String>(fabricMaterialComboBoxModel);
private JComboBox<String> fabricColorComboBox = new JComboBox<String>(materialColorComboBoxModel);
public PDialogMaterial(){
}
public void addMainFrameChildrenListener(MainFrameChildrenListener listener) {
this.listener = listener;
}
public void removeMainFrameChildrenListener() {
this.listener = null;
}
public void firePDialogMaterialEventOccured(MainFrameChildrenEventObject event) {
this.listener.dialogEventOccured(event);
}
public ImageIcon getPicture(String path) {
URL link = this.getClass().getResource(path);
ImageIcon icon = new ImageIcon(link);
return icon;
}
public void setFabricMask() {
gc.gridx = 0;
gc.gridy = 0;
gc.gridwidth = 1;
gc.gridheight = 1;
gc.weightx = 1;
gc.weighty = 1;
gc.anchor = GridBagConstraints.CENTER;
// First line - picture
gc.gridwidth = 2;
this.add(new JLabel(getPicture("/images/material_32pos.gif")), gc);
gc.gridwidth = 1;
// Second line - name
gc.gridy++;
this.add(new JLabel("Name: "), gc);
gc.gridx++;
this.add(nameField, gc);
// Third line - material
gc.gridx--;
gc.gridy++;
this.add(new JLabel("Material: "), gc);
gc.gridx++;
this.add(fabricMaterialComboBox, gc);
// Fourth line - vendor name
gc.gridx--;
gc.gridy++;
this.add(new JLabel("Vendor: "), gc);
gc.gridx++;
this.add(vendorField, gc);
// Fifth line - predominating color
gc.gridx--;
gc.gridy++;
this.add(new JLabel("Predominaing color: "), gc);
gc.gridx++;
this.add(fabricColorComboBox, gc);
// Sixth line - price
gc.gridx--;
gc.gridy++;
this.add(new JLabel("Price per square meter: "), gc);
gc.gridx++;
this.add(priceField, gc);
// Seventh line - control buttons
gc.gridx--;
gc.gridy++;
this.add(okButton, gc);
gc.gridx++;
this.add(cancelButton, gc);
}
public void setStrapMask() {
gc.gridx = 0;
gc.gridy = 0;
gc.gridwidth = 1;
gc.gridheight = 1;
gc.weightx = 1;
gc.weighty = 1;
gc.anchor = GridBagConstraints.CENTER;
// First line - picture
gc.gridwidth = 2;
this.add(new JLabel(getPicture("/images/material_32pos.gif")), gc);
gc.gridwidth = 1;
// Second line - name
gc.gridy++;
this.add(new JLabel("Name: "), gc);
gc.gridx++;
this.add(nameField, gc);
// Third line - strap width
gc.gridx--;
gc.gridy++;
this.add(new JLabel("Width: "), gc);
gc.gridx++;
this.add(widthField, gc);
// Fourth line - predominating color
gc.gridx--;
gc.gridy++;
this.add(new JLabel("Predominaing color: "), gc);
gc.gridx++;
this.add(fabricColorComboBox, gc);
// Fifth line - strap price
gc.gridx--;
gc.gridy++;
this.add(new JLabel("Price per meter: "), gc);
gc.gridx++;
this.add(priceField, gc);
// Sixth line - control buttons
gc.gridx--;
gc.gridy++;
this.add(okButton, gc);
gc.gridx++;
this.add(cancelButton, gc);
}
public void constructPDialogMaterial(int maskType){
this.setLayout(new GridBagLayout());
this.setLocationRelativeTo(this.getParent());
this.setDefaultCloseOperation(PDialog.DISPOSE_ON_CLOSE);
this.setSize(size);
this.setResizable(false);
this.setVisible(false);
this.setIconImage(getPicture("/images/material_32pos.gif").getImage());
this.nameField.setBackground(this.getBackground());
this.vendorField.setBackground(this.getBackground());
this.priceField.setBackground(this.getBackground());
switch (maskType) {
case PDialogMaterial.FABRIC_MASK:
this.setTitle("Fabric material");
setFabricMask();
break;
case PDialogMaterial.STRAP_MASK:
this.setTitle("Straps");
setStrapMask();
break;
// TODO
default:
System.out.println("Oh noes! Something happend!");
}
okButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent event) {
String priceString = dfc.removeWhitespacesAndSwapCommas(priceField.getText());
if(dfc.testDoubleFormat(priceString)){
Double price = Double.valueOf(priceString);
MainFrameChildrenEventObject eventObject = new MainFrameChildrenEventObject(okButton, vendorField.getText(), nameField.getText(),
(String)materialColorComboBoxModel.getSelectedItem(), (String)materialColorComboBoxModel.getSelectedItem(),
price, PDialog.MATERIAL_EVENT_FABRIC);
firePDialogEvent(eventObject);
dispose();
}
else{
JOptionPane.showMessageDialog(PDialogMaterial.this, "Wrong price format", "Format error",
JOptionPane.WARNING_MESSAGE);
}
}
});
cancelButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent arg0) {
dispose();
}
});
}
}
PDialogCustomer的完整代码(工作示例):
package view.dialogs;
import java.awt.GridBagConstraints;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.net.URL;
import javax.swing.BorderFactory;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JLabel;
import javax.swing.JTextField;
import view.listeners.MainFrameChildrenEventObject;
public class PDialogCustomer extends PDialog {
private static final long serialVersionUID = 8431597688560531951L;
private GridBagConstraints gc = new GridBagConstraints();
private URL imageLink;
private URL iconLink;
// New customer GUI setup
JLabel nameLabel = new JLabel("Customer name: ");
JLabel addressLabel = new JLabel("Customer address: ");
JLabel dogLabel = new JLabel("Dog name: ");
JTextField nameField = new JTextField(8);
JTextField streetField = new JTextField(8);
JTextField cityField = new JTextField(8);
JTextField countryField = new JTextField(8);
JTextField dogField = new JTextField(8);
JButton okBttn = new JButton("Ok");
JButton cancelBttn = new JButton("Cancel");
// ________________________________________________________
public PDialogCustomer() {
String imagePath = "/images/customer_32pos.gif";
String iconPath = "/images/customer_16pos.gif";
this.iconLink = getClass().getResource(iconPath);
this.setIconImage(new ImageIcon(iconLink).getImage());
this.imageLink = getClass().getResource(imagePath);
this.setTitle("New customer");
nameField.setBorder(BorderFactory.createEtchedBorder());
nameField.setBackground(this.getBackground());
streetField.setBorder(BorderFactory.createTitledBorder("Street"));
streetField.setBackground(this.getBackground());
cityField.setBorder(BorderFactory.createTitledBorder("City"));
cityField.setBackground(this.getBackground());
countryField.setBorder(BorderFactory.createTitledBorder("Country"));
countryField.setBackground(this.getBackground());
dogField.setBorder(BorderFactory.createTitledBorder("Dogs name"));
dogField.setBackground(this.getBackground());
gc.weightx = 1;
gc.weighty = 1;
gc.gridheight = 1;
gc.gridwidth = 2;
gc.gridx = 0;
gc.gridy = 0;
gc.anchor = GridBagConstraints.CENTER;
add(new JLabel(new ImageIcon(imageLink)));
gc.gridwidth = 1;
gc.gridy++;
add(nameLabel, gc);
gc.gridx++;
add(nameField, gc);
gc.gridy++;
gc.gridx--;
add(addressLabel, gc);
gc.gridx++;
add(streetField, gc);
gc.gridy++;
add(cityField, gc);
gc.gridy++;
add(countryField, gc);
gc.gridy++;
gc.gridx--;
add(dogLabel, gc);
gc.gridx++;
add(dogField, gc);
gc.gridy++;
gc.gridx--;
add(okBttn, gc);
gc.gridx++;
add(cancelBttn, gc);
okBttn.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
String address = streetField.getText() + ", " + cityField.getText() + ", " + countryField.getText();
firePDialogEvent(new MainFrameChildrenEventObject(okBttn, nameField.getText(), address,
dogField.getText(), PDialog.CUSTOMER_EVENT));
dispose();
}
});
cancelBttn.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
dispose();
}
});
}
}
最佳答案
令人反感的类中的问题是它重新声明了
private MainFrameChildrenListener listener;
领域。因此,您有两个名称相同的私有字段,一个在超类中,一个在子类中。当您使用子类中的方法时,子类中的一个将覆盖超类中的一个,但对于超类中定义的方法不可见。删除子类中的侦听器字段,它应该可以工作。
关于java - 无法将听众分配给类(class),我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/39315428/