कोड से जावा स्विंग एप्लिकेशन को कैसे बंद करें


94

कोड से एक स्विंग एप्लिकेशन को समाप्त करने का उचित तरीका क्या है, और नुकसान क्या हैं?

मैं एक टाइमर आग के बाद अपने आवेदन को स्वचालित रूप से बंद करने की कोशिश करता था। लेकिन अभी बुला dispose()पर JFrameचाल नहीं किया - खिड़की गायब हो गई लेकिन आवेदन को समाप्त नहीं किया। हालाँकि जब विंडो को क्लोज बटन से बंद करते हैं, तो एप्लिकेशन समाप्त हो जाता है। मुझे क्या करना चाहिए?


कृपया अपने टाइमर का एक कोड स्निपेट पोस्ट करें।
जेम्स स्कैच

जवाबों:


106

आपके JFrame डिफ़ॉल्ट क्लोज एक्शन को DISPOSE_ON_CLOSEइसके बजाय " " पर सेट किया जा सकता है EXIT_ON_CLOSE(लोग EXIT_ON_CLOSE का उपयोग क्यों नहीं करते हैं) से परे है।

यदि आपके पास कोई अपरिहार्य खिड़कियां या गैर-डेमॉन थ्रेड हैं, तो आपका आवेदन समाप्त नहीं होगा। इसे एक त्रुटि माना जाना चाहिए (और इसे System.exit के साथ हल करना बहुत बुरा विचार है)।

सबसे आम अपराधी java.util.Timer हैं और आपके द्वारा बनाया गया एक कस्टम थ्रेड है। दोनों को डेमॉन पर सेट किया जाना चाहिए या स्पष्ट रूप से मार दिया जाना चाहिए।

यदि आप सभी सक्रिय फ़्रेमों की जांच करना चाहते हैं, तो आप उपयोग कर सकते हैं Frame.getFrames()। यदि सभी विंडोज / फ्रेम्स का निपटारा किया जाता है, तो किसी भी गैर-डेमॉन थ्रेड्स के लिए डिबगर का उपयोग करें जो अभी भी चल रहे हैं।


मेरे मामले में मुझे डीबगर से पता चला कि मेरे पास अभी भी एक स्विंगवर्कर था। मैंने WindowClose Eventlistener में इसकी रद्द (सच्ची) विधि को कहा और अब यह कार्यक्रम समाप्त हो गया। धन्यवाद!
हंस-पीटर स्टॉर्र

ध्यान दें कि आपको प्रत्येक फ्रेम पर निपटान को कॉल करना पड़ सकता है, और आमतौर पर यह "पर्याप्त" है (हालांकि EXIT_ON_CLOSE के लिए डिफ़ॉल्ट करीबी कार्रवाई सेट करना संभवतः बुरा विचार नहीं है)।
रोवरडपैक

क्या होगा यदि आपके पास एक खिड़की दूसरे को खोल रही है, लेकिन स्वयं को डिस्पोज़ नहीं कर रही है, ताकि आप इसे backखिड़की के लिए उपयोग कर सकें ? यदि दूसरी विंडो बंद हो जाती है और आप DISPOSE_ON_CLOSEप्रोग्राम का उपयोग नहीं करते हैं तो समाप्त नहीं होता है क्योंकि पहली विंडो अभी भी "अनडिस्पॉन्डेड" है ... क्या इसका उपयोग करने के बिना हल करने का कोई तरीका है DISPOSE_ON_CLOSE?
स्वेन्द हेन्सन

पहली खिड़की को खुद को दूसरी खिड़की के श्रोता के रूप में जोड़ना चाहिए और उचित कार्रवाई करनी चाहिए।
जेम्स स्कैच

3
EXIT_ON_CLOSE के उपयोग से आवेदन को जबरन समाप्त कर दिया जाएगा। यदि आपको कार्यक्रम से बाहर निकलने से पहले कार्रवाई करने की आवश्यकता है (जैसे काम करने वाले डेटा को सहेजना), तो आपको सामान्य स्विंग इवेंट हैंडलर का उपयोग करने के बजाय केवल जेवीएम इवेंट हैंडलर में टैप करना होगा। दोनों "काम" करेंगे, लेकिन EXIT_ON_CLOSE अधिक जटिल एप्लिकेशन के लिए समस्याएं पैदा करेगा।
जेम्स स्कैच

34

मुझे एक EXIT_ON_CLOSE लगता है

frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

इससे पहले System.exit(0)कि आप ऐप छोड़ने से पहले कुछ सफाई संचालन करने के लिए विंडो श्रोता लिख सकते हैं, इससे पहले कि बेहतर हो ।

वह विंडो श्रोता आपको परिभाषित करने की अनुमति देता है:

public void windowClosing(WindowEvent e) {
    displayMessage("WindowListener method called: windowClosing.");
    //A pause so user can see the message before
    //the window actually closes.
    ActionListener task = new ActionListener() {
        boolean alreadyDisposed = false;
        public void actionPerformed(ActionEvent e) {
            if (frame.isDisplayable()) {
                alreadyDisposed = true;
                frame.dispose();
            }
        }
    };
    Timer timer = new Timer(500, task); //fire every half second
    timer.setInitialDelay(2000);        //first delay 2 seconds
    timer.setRepeats(false);
    timer.start();
}

public void windowClosed(WindowEvent e) {
    //This will only be seen on standard output.
    displayMessage("WindowListener method called: windowClosed.");
}

16

प्रयत्न:

System.exit(0);

क्रूड, लेकिन प्रभावी।


दुर्भाग्य से यह मेरे लिए बहुत कच्चा है। मैं चाहता हूं कि विंडो क्लोजिंग इवेंट्स को कुछ क्लीनअप क्रियाओं के लिए संसाधित किया जाए। ठीक है, मैं एक SwingUtils.invokeLater के साथ System.exit कर सकता हूं, लेकिन मैं उचित काम करूंगा।
हंस-पीटर स्टॉर 12

5
System.exit (0) केवल क्रूड नहीं है, यह बुराई है। सभी फ़्रेमों की जांच करें, कॉल डिस्पोज़ करें। यदि वह विफल हो जाता है, तो डिबगर चलाएं और देखें कि क्या गैर-डेमन थ्रेड अभी भी जीवित हैं।
जेम्स स्कैच

JDK में बहुत सारे बग हैं जो प्रक्रिया के बारे में छोड़ते हैं। तो +1 से बाहर निकलें (), लेकिन आप इसे डिबग बिल्ड में अक्षम करना चाहते हैं।
टॉम हॉल्टिन -

11

हो सकता है सुरक्षित तरीका कुछ इस तरह है:

    private JButton btnExit;
    ...
    btnExit = new JButton("Quit");      
    btnExit.addActionListener(new ActionListener() {
        public void actionPerformed(ActionEvent e){
            Container frame = btnExit.getParent();
            do 
                frame = frame.getParent(); 
            while (!(frame instanceof JFrame));                                      
            ((JFrame) frame).dispose();
        }
    });

3
Frameएक बड़े अक्षर के साथ एक चर नाम रखने के लिए बहुत खराब शैली , बिल्कुल एक वर्ग के नाम की तरह ...
ज्यां-फिलिप पेलेट

आपको बहुत - बहुत धन्यवाद! यह सबसे अच्छे तरीकों में से एक है!
razaeeff

9

निम्न प्रोग्राम में कोड शामिल है जो स्पष्ट रूप से System.exit () को बुलाए बिना बाहरी थ्रेड्स की कमी वाले प्रोग्राम को समाप्त करेगा। थ्रेड्स / श्रोताओं / टाइमर / आदि का उपयोग करते हुए अनुप्रयोगों के लिए इस उदाहरण को लागू करने के लिए, एक को केवल सफाई कोड डालने का अनुरोध करना चाहिए (और, यदि लागू हो, प्रतीक्षा) WindowEvent से पहले मैन्युअल रूप से कार्रवाई शुरू होने से पहले उनकी समाप्ति की कार्रवाई की गई है ()।

उन लोगों के लिए जो कोड / पेस्ट कोड को चलाने में सक्षम हैं जैसा कि दिखाया गया है, थोड़ा-सा बदसूरत लेकिन अन्यथा अप्रासंगिक मुख्य विधि अंत में शामिल है।

public class CloseExample extends JFrame implements ActionListener {

    private JButton turnOffButton;

    private void addStuff() {
        setDefaultCloseOperation(DISPOSE_ON_CLOSE);
        turnOffButton = new JButton("Exit");
        turnOffButton.addActionListener(this);
        this.add(turnOffButton);
    }

    public void actionPerformed(ActionEvent quitEvent) {
        /* Iterate through and close all timers, threads, etc here */
        this.processWindowEvent(
                new WindowEvent(
                      this, WindowEvent.WINDOW_CLOSING));
    }

    public CloseExample() {
        super("Close Me!");
        addStuff();
    }

    public static void main(String[] args) {
        java.awt.EventQueue.invokeLater(new Runnable() {
            public void run() {
                CloseExample cTW = new CloseExample();
                cTW.setSize(200, 100);
                cTW.setLocation(300,300);
                cTW.setVisible(true);
            }
        });
    }
}

4

यदि मैं आपको सही ढंग से समझता हूं कि आप एप्लिकेशन को बंद करना चाहते हैं, भले ही उपयोगकर्ता क्लोज बटन पर क्लिक न करें। शायद आपको अपनी जरूरतों को बेहतर करने के लिए addWindowListener () या enableEvents () के साथ WindowEvents को पंजीकृत करना होगा।

आप तब कॉल कर सकते हैं घटना को कॉल करने के लिए processWindowEvent () के साथ। यहां एक नमूना कोड है जो JFrame बनाएगा, 5 सेकंड प्रतीक्षा करें और उपयोगकर्ता सहभागिता के बिना JFrame बंद करें।

import javax.swing.*;
import java.awt.*;
import java.awt.event.*;

public class ClosingFrame extends JFrame implements WindowListener{

public ClosingFrame(){
    super("A Frame");
    setSize(400, 400);
            //in case the user closes the window
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            setVisible(true);
            //enables Window Events on this Component
            this.addWindowListener(this);

            //start a timer
    Thread t = new Timer();
            t.start();
    }

public void windowOpened(WindowEvent e){}
public void windowClosing(WindowEvent e){}

    //the event that we are interested in
public void windowClosed(WindowEvent e){
    System.exit(0);
}

public void windowIconified(WindowEvent e){}
public void windowDeiconified(WindowEvent e){}
public void windowActivated(WindowEvent e){}
public void windowDeactivated(WindowEvent e){}

    //a simple timer 
    class Timer extends Thread{
           int time = 10;
           public void run(){
     while(time-- > 0){
       System.out.println("Still Waiting:" + time);
               try{
                 sleep(500);                     
               }catch(InterruptedException e){}
             }
             System.out.println("About to close");
    //close the frame
            ClosingFrame.this.processWindowEvent(
                 new WindowEvent(
                       ClosingFrame.this, WindowEvent.WINDOW_CLOSED));
           }
    }

    //instantiate the Frame
public static void main(String args[]){
          new ClosingFrame();
    }

}

जैसा कि आप देख सकते हैं, ProcessWindowEvent () विधि WindowClosed घटना को निकाल दिया जाता है जहां आपको एप्लिकेशन को बंद करने से पहले यदि आवश्यक हो तो कुछ सफाई कोड करने के लिए एक oportunity है।


windowClosed को डिस्पोज़ () नहीं होना चाहिए। System.exit (0)।
जेम्स स्कैच

2

Oracle दस्तावेज़ीकरण पर एक नज़र डालें ।

JDK 1.4 से शुरू एक आवेदन समाप्त हो जाता है अगर:

  • कोई प्रदर्शित करने योग्य AWT या स्विंग घटक नहीं हैं।
  • देशी घटना कतार में कोई मूल घटना नहीं हैं।
  • जावा EventQueues में कोई AWT ईवेंट नहीं हैं।

Cornercases:

दस्तावेज़ में कहा गया है कि कुछ पैकेज प्रदर्शित किए बिना प्रदर्शन योग्य घटक बनाते हैं। एक प्रोग्राम जो टूलकिट .getDefaultToolkit कहता है () समाप्त नहीं होगा। एक उदाहरण के रूप में दिया गया है।

इसके अलावा अन्य प्रक्रियाएं AWT को जीवित रख सकती हैं, जब वे, कभी भी किस कारण से, घटनाओं को मूल घटना कतार में भेज रही हैं।

इसके अलावा, मैंने देखा कि कुछ सिस्टम्स पर एप्लिकेशन को वास्तव में समाप्त होने से पहले कुछ सेकंड का समय लगता है।


0

मुझे लगता है, विचार यहाँ WindowListener है - आप किसी भी कोड को जोड़ सकते हैं जिसे आप उस चीज़ से पहले चलाना चाहेंगे


0

अन्य टिप्पणियों के जवाब में, DISPOSE_ON_CLOSE को एप्लिकेशन को ठीक से बाहर निकलने के लिए प्रतीत नहीं होता है - यह केवल विंडो को नष्ट कर देता है, लेकिन एप्लिकेशन चालू रहेगा। यदि आप आवेदन को समाप्त करना चाहते हैं तो EXIT_ON_CLOSE का उपयोग करें।


यह प्रतिक्रिया जेम्स स्केक के उत्तर के बिल्कुल विपरीत है। कौनसा सही है? (जब मैं एक साधारण अनुप्रयोग के साथ परीक्षण करता हूं, तो दोनों काम करने लगते हैं ...)
या मैपर

याद नहीं है कि मैंने इसे अभी कैसे परीक्षण किया।
JSideris
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.