2012-04-19 15 views
5

मेरे पास एक सारणी कक्षा के साथ एक अनुप्रयोग है जो JDialog फैलाता है। एक abstract void onClose() के रूप में वर्ग, और वर्ग के निर्माता में, निम्नलिखित कोड जोड़ा जाता है:'विंडो लिस्टनर' अभिनय, शाश्वत फायरिंग

addWindowListener(new WindowAdapter() { 
    @Override 
    public void windowClosed(WindowEvent e) { 
     onClose(); 
    } 
} 

घटना जब उम्मीद निकाल दिया जाता है, लेकिन फिर एक अजीब बात होता है। जब इस कक्षा के एक ठोस विस्तार में onClose() विधि में नया JDialog बनाने के लिए कोड है, और यह JDialog का defaultCloseOperationJDialog.DISPOSE_ON_CLOSE है, तब तक ईवेंट लगातार निकाल दिया जाता है, जब तक कि मैं ऑपरेशन छोड़ने को मजबूर नहीं करता।

मैं निम्नलिखित SSCCE को कोड अलग है: "मुझे क्लिक करें" बटन पर क्लिक करने पर

// package removed 
// imports removed 
public class SSCCE extends JDialog { 
    public static void main(String[] args) { 
     SSCCE s = new SSCCE(); 
     s.pack(); 
     s.setVisible(true); 
    } 
    public SSCCE() { 
     setLayout(new GridLayout(1, 0, 0, 0)); 
     JButton btn = new JButton("click me"); 
     btn.addActionListener(new ActionListener() { 
      @Override 
      public void actionPerformed(ActionEvent arg0) { 
       dispose(); 
      } 
     }); 
     addWindowListener(new WindowAdapter() { 
      @Override 
      public void windowClosed(WindowEvent e) { 
       System.out 
         .println("SSCCE.SSCCE().new WindowAdapter() {...}.windowClosed()"); 
       onClose(); 
      } 
     }); 
     add(btn); 
    } 

    public void onClose() { 
     JDialog dialog = new JDialog(); 
     dialog.setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE); 
     dialog.setVisible(true); 
    } 

} 

, खाली JDialog प्रकट होता है और SSCCE.SSCCE().new WindowAdapter() {...}.windowClosed() कंसोल विंडो में दिखाई देता है। जब मैं खाली संवाद बंद करता हूं, तो यह फिर से दिखाई देता है और पाठ फिर से दिखाई देता है।

जब "क्लिक पर क्लिक:

एक और वास्तव में दिलचस्प बात यह है कि मैं कंसोल में निम्न उत्पादन हो जब मैं

JDialog dialog = new JDialog() { 
     @Override 
     public synchronized void addWindowListener(WindowListener l) { 
      super.addWindowListener(l); 
      System.out 
        .println("SSCCE.onClose().new JDialog() {...}.addWindowListener()"); 
     } 
    }; 

को

JDialog dialog = new JDialog(); 

से प्रारंभ लाइन बदल रहा है मुझे "बटन:

SSCCE.SSCCE().new WindowAdapter() {...}.windowClosed() 
SSCCE.onClose().new JDialog() {...}.addWindowListener() 
SSCCE.onClose().new JDialog() {...}.addWindowListener() 

संवाद के पहले समापन पर:

SSCCE.SSCCE().new WindowAdapter() {...}.windowClosed() 
SSCCE.onClose().new JDialog() {...}.addWindowListener() 
SSCCE.onClose().new JDialog() {...}.addWindowListener() 
SSCCE.onClose().new JDialog() {...}.addWindowListener() 
SSCCE.onClose().new JDialog() {...}.addWindowListener() 

संवाद के दूसरे समापन पर:

SSCCE.SSCCE().new WindowAdapter() {...}.windowClosed() 
SSCCE.onClose().new JDialog() {...}.addWindowListener() 
SSCCE.onClose().new JDialog() {...}.addWindowListener() 
SSCCE.onClose().new JDialog() {...}.addWindowListener() 
SSCCE.onClose().new JDialog() {...}.addWindowListener() 
SSCCE.onClose().new JDialog() {...}.addWindowListener() 

हर बार जब मैं संवाद बंद, addWindowListener(WindowListener l), एक अतिरिक्त समय कहा जाता है, भले ही यह जानबूझकर इसे बुला रहा नहीं है।

मैं नहीं है वास्तव में किसी भीWindowListener रों संवाद पर पंजीकृत होना चाहते हैं, लेकिन मुझे लगता है कि बस addWindowListener(...) विधि अधिभावी और बुला super.addWindowListener(...) भी खराब नहीं होगा।

मैक ओएस एक्स 10.6.8 पर जावा 1.6.0_31 चला रहा हूं, एक्लिप्स इंडिगो (विंडोबिल्डर के साथ, यदि यह मायने रखता है) का उपयोग कर।

क्या किसी के पास कोई विचार है?

धन्यवाद!

उत्तर

7

Java Dialog tutorial के अनुसार,

हर संवाद एक फ्रेम घटक पर निर्भर है। जब वह फ्रेम नष्ट हो जाता है, तो इसके आश्रित संवाद भी होते हैं।

आप JDialog constructor without any arguments उपयोग करते हैं, यह

एक शीर्षक के बिना और एक निर्दिष्ट फ्रेम मालिक के बिना प्रणाली का डायलॉग बनाता है। एक साझा, छुपा फ्रेम संवाद के मालिक के रूप में सेट किया जाएगा।

कि छिपा फ्रेम साझा SwingUtilities$SharedOwnerFrame है, और प्रारंभ पर यह सब स्वामित्व वाली खिड़कियों के लिए एक WindowListener पंजीकृत करता है।

जब आप अपने संवाद, SharedOwnerFrame के windowClosed विधि कहा जाता है, जिससे सभी विंडो यह मालिक के लिए जाँच करता (इस बिंदु पर मूल SSCCE संवाद और नए एक है) बंद करते हैं, इस पर किसी ने दिखाई दे रहे हैं, और इसलिए यह पाता है खुद को निपटाता है। इसका अपने सभी संवादों का निपटान करने का असर पड़ता है, जो प्रत्येक के लिए एक विंडो बंद घटना पोस्ट करता है। यह आपके श्रोता में windowClosed पर कॉल करता है, एक नया संवाद खोलता है। और दौर हम फिर से जाते हैं :-)। आपकी आखिरी टिप्पणियों के बारे में, आपको हर बार अतिरिक्त लॉग लाइन मिलती हैं क्योंकि आपको SharedOwnerFrame का एक संवाद मिलता है।

आप SSCCE संवाद करते हैं खुद नया संवाद तो आप साझा स्वामित्व के साथ अंत नहीं है और यह ठीक काम करता है (इसके निर्माता में this पास करके):

public void onClose() { 
    JDialog dialog = new JDialog(this); 
    dialog.setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE); 
    dialog.setVisible(true); 
} 
+0

धन्यवाद! यह सही समझ में आता है। – wchargin

4
import java.awt.GridLayout; 
import java.awt.event.ActionEvent; 
import java.awt.event.ActionListener; 
import java.awt.event.WindowAdapter; 
import java.awt.event.WindowEvent; 

import javax.swing.JButton; 
import javax.swing.JDialog; 
import javax.swing.JOptionPane; 

public class SSCCE extends JDialog { 
    public static void main(String[] args) { 
     SSCCE s = new SSCCE(); 
     s.pack(); 
     s.setVisible(true); 
    } 

    private WindowAdapter wa = new WindowAdapter() { 
     @Override 
     public void windowClosed(WindowEvent e) { 
      System.out 
        .println("SSCCE.SSCCE().new WindowAdapter() {...}.windowClosed()"); 
      onClose(); 
     } 
    }; 

    public SSCCE() { 
     setLayout(new GridLayout(1, 0, 0, 0)); 
     JButton btn = new JButton("click me"); 
     btn.addActionListener(new ActionListener() { 
      @Override 
      public void actionPerformed(ActionEvent arg0) { 
       dispose(); 
      } 
     }); 
     addWindowListener(
     wa); 
     add(btn); 
    } 

    public void onClose() { 
     removeWindowListener(wa); 
     JDialog dialog = new JDialog(); 
     dialog.setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE); 
     dialog.setVisible(true); 

    } 

} 
+0

मैं देख रहा हूँ कि तुम क्या ' मैंने किया है, और मैं देखता हूं कि यह क्यों काम करता है, लेकिन मैं वास्तव में सोच रहा हूं कि क्यों श्रोता ('वा') पहली जगह 'संवाद' में जोड़ा जा रहा है। क्या आप मुझे समझा सकते हैं क्यों? – wchargin

+0

मेरी इच्छा है कि आपके पास आपके लिए अच्छा जवाब हो। मुझे लगता है कि इसे इस तथ्य से निपटना पड़ सकता है कि आपकी कक्षा जेडियलोग को बढ़ाती है। – ControlAltDel

+0

उपयोगकर्ता 12 9 14 9 2 'इस तथ्य के साथ कि आपकी कक्षा JDialog'+++++ 1k, बिल्कुल – mKorbel