2016-09-04 1 views
0

私の問題は、不可解な無能さにあります。クラスにリスナーを割り当てようとするときのトラブル

ソフトウェアは、メインフレームと呼ばれるのJFrameの子クラスが複数にダイアログを聞いているJavaのSwingベースのデスクトップアプリケーションです。すべてのダイアログウィンドウは、リスナー関連の変数と関数を運ぶPDialogクラスの子です。だから私は、私は成功し、彼らがPDialogの子クラスとして継承された機能を使用してに耳を傾ける3つのダイアログを作成している

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(); 
} 
} 

:これはPDialogクラスは次のようになります。メインフレームクラスは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()メソッドのためnullポインタ例外を取得します。 リスナーをPDialogMaterialクラスのコンストラクタを介して渡そうとしましたが、PDialogMaterialクラス内で新しいメソッドを作成しようとしても、リスナーを渡すことはできませんでした。

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); 

    } 
} 

あります:私は物事を動作させることができた唯一の方法は、公共を宣言(!EEK)などは以下のようにメインフレームのコンストラクタから、それは直接(!eeeeek)にアクセスされた新しいMainFrameChildrenListener変数を作成しましたなぜすべて継承した4つのクラスのうちの3つがと同じかリスナハンドリングメソッドは4番目のクラスとは異なる振る舞いをしていますか?私は何が欠けていますか?

コメントフォロー:

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(); 
      } 
     }); 
    } 
} 
+2

1)優れたヘルプを表示する:

は、この問題を説明するために、私は小さな例を構築しました.sscce.org /)。 2)「スタックトレースとは何ですか?アプリケーションエラーをデバッグするにはどうすれば使用できますか?」(http://stackoverflow.com/q/3988788/418556)&[Null Pointer Exceptionとは何ですか?私はそれを修正?](http://stackoverflow.com/q/218384/418556) –

+0

'PDialogMaterial'のコードと' PDialogOrder'のような他のコードの1つを投稿します。 – c0der

+0

@AndrewThompson私はスタックトレースをたどり、ヌルポインタを投げたメソッドを見つけました。他のクラスがこのメソッドを問題なく使用するので、私はソリューションに近づけませんでした。シンプルなクラスでスクラッチレクレーションをした後、私は再び例外を取得しませんでした。私は最小、完全、そして実証可能な例を扱っていますが、それには時間がかかるかもしれません:(モデルとコントローラの部分が必要ですか? – Avo

答えて

2

問題における問題クラスはそれを再宣言することです

private MainFrameChildrenListener listener; 

フィールド。したがって、スーパークラスには2つのプライベートフィールドがあり、サブクラスには同じ名前のプライベートフィールドが2つあります。サブクラス内のメソッドは、そのサブクラスのメソッドにあるときにスーパークラスのメソッドをオーバーライドしますが、スーパークラスに定義されているメソッドでは表示されません。サブクラスのリスナーフィールドを削除すると、正常に動作するはずです。

+0

ありがとう!私のスパゲッティソフトウェアを使いこなすためにあなたの努力と時間をいただきありがとうございます!そして今私はついに続けることができます。 – Avo

1

Markusすでに言われているように、機能していないリスナーでは、リスナーフィールドを隠していて、セッターを再宣言しています。// WWW:早く、[MCVE]または[ショート、自炊、正しい例](HTTPを投稿

import java.util.Arrays; 

public class HiddenField { 

    static abstract class Base { 
     String field = "BASE"; 

     // sets the base's field 
     void setField(String set) { 
      this.field = set; 
     } 

     // ensures not to be overridden and returns the base's field. 
     final String getField() { 
      return this.field; 
     } 

     // access the field by getter (ensured to be base) and field 'field' 
     @Override 
     public String toString() { 
      return this.getClass().getSimpleName() + ": get()->" + getField() + " vs. field->" + field; 
     } 
    } 

    static class ProperExtension extends Base { 
     /* no need to override the base's field */ 
    } 

    static class HidingExtension extends Base { 

     // this field isn't related to the one in Base, but has the same name! 
     String field = "HIDING"; 

     // the setter is overridden (exact copy!) but because of the same-named 
     // field in this extending class, it sets this class's field and not the 
     // one in the base-class! 
     @Override 
     void setField(String set) { 
      this.field = set; 
     } 

     // copied the toString from above - here it is accessing the 
     // base-class's field via getter and this class's field directly. 
     @Override 
     public String toString() { 
      return this.getClass().getSimpleName() + ": get()->" + getField() + " vs. field->" + field; 
     } 
    } 

    public static void main(String[] args) { 
     // build both types of extending classes and invoke their setters 
     Arrays.asList(new ProperExtension(), new HidingExtension()).forEach(obj -> { 
      System.out.println("before ~> " + obj); 
      obj.setField("SET"); 
      System.out.println("after ~> " + obj + "\n"); 
     }); 
    } 
} 
関連する問題