কোড থেকে জাভা সুইং অ্যাপ্লিকেশনটি কীভাবে বন্ধ করবেন


94

কোড থেকে একটি সুইং অ্যাপ্লিকেশন সমাপ্ত করার সঠিক উপায় কী এবং কী কী সমস্যা রয়েছে?

আমি টাইমার ফায়ার হওয়ার পরে আমার অ্যাপ্লিকেশনটি স্বয়ংক্রিয়ভাবে বন্ধ করার চেষ্টা করব। কিন্তু কলিং dispose()উপর JFrameকৌতুক করিনি - জানালা বিলুপ্ত কিন্তু আবেদন বিনষ্ট হয়নি। তবে ক্লোজ বোতামটি দিয়ে উইন্ডোটি বন্ধ করার সময়, অ্যাপ্লিকেশনটি সমাপ্ত হবে। আমার কি করা উচিৎ?


আপনার টাইমার একটি কোড স্নিপেট পোস্ট করুন।
জেমস শেক

উত্তর:


106

আপনার জেফ্রেমের ডিফল্ট ঘনিষ্ঠ ক্রিয়াটি " DISPOSE_ON_CLOSE" এর পরিবর্তে সেট করা যেতে পারে EXIT_ON_CLOSE(কেন লোকেরা EXIT_ON_CLOSE ব্যবহার করা আমার বাইরে নয়)।

আপনার যদি কোনও নির্বিঘ্নিত উইন্ডোজ বা নন-ডেমন থ্রেড থাকে তবে আপনার অ্যাপ্লিকেশনটি শেষ হবে না। এটি একটি ত্রুটি হিসাবে বিবেচনা করা উচিত (এবং এটি System.exit দিয়ে সমাধান করা খুব খারাপ ধারণা)।

সর্বাধিক সাধারণ অপরাধীরা হ'ল java.util.Timer এবং আপনার তৈরি করা একটি কাস্টম থ্রেড। উভয়ই ডিমন সেট করা উচিত বা স্পষ্টভাবে হত্যা করা উচিত।

আপনি যদি সমস্ত সক্রিয় ফ্রেমগুলি পরীক্ষা করতে চান তবে আপনি ব্যবহার করতে পারেন Frame.getFrames()। যদি সমস্ত উইন্ডোজ / ফ্রেমগুলি নিষ্পত্তি করা হয়, তবে কোনও নন-ডেমন থ্রেড যা এখনও চলছে তা পরীক্ষা করতে একটি ডিবাগার ব্যবহার করুন।


আমার ক্ষেত্রে আমি ডিবাগারটির সাথে আবিষ্কার করেছি যে আমার একটি সুইং ওয়ার্কার এখনও সক্রিয় রয়েছে। আমি এর বাতিল (সত্য) পদ্ধতিটিকে উইন্ডোক্লোজ ইভেন্টলিস্টনারে ডেকেছি এবং প্রোগ্রামটি এখন শেষ হচ্ছে। ধন্যবাদ!
হ্যান্স-পিটার স্টার

নোট করুন যে আপনাকে প্রতিটি ফ্রেমে ডিসপোজ কল করতে হতে পারে, এবং সাধারণত এটি "যথেষ্ট" (যদিও ডিফল্ট নিকট কর্মটি EXIT_ON_CLOSE এ সেট করা সম্ভবত কোনও খারাপ ধারণা নয়)।
রজারডপ্যাক

যদি আপনার একটি উইন্ডো অন্য উইন্ডোটি খোলার থাকে তবে নিজেই নিষ্পত্তি না করে, যাতে আপনি এটি একটি backউইন্ডোর জন্য ব্যবহার করতে পারেন ? দ্বিতীয় উইন্ডোটি যদি তখন বন্ধ হয়ে যায় এবং আপনি DISPOSE_ON_CLOSEপ্রোগ্রামটি ব্যবহার করেন তবে শেষ হবে না কারণ প্রথম উইন্ডোটি এখনও "নির্বিঘ্নিত" ... ব্যবহার না করে সমাধান করার কোনও উপায় আছে DISPOSE_ON_CLOSE?
সোভেন্ড হ্যানসেন

প্রথম উইন্ডোটি দ্বিতীয় উইন্ডোতে শ্রোতা হিসাবে নিজেকে যুক্ত করা উচিত এবং যথাযথ ব্যবস্থা গ্রহণ করা উচিত।
জেমস শেক

4
EXIT_ON_CLOSE ব্যবহার করার ফলে অ্যাপ্লিকেশনটি জোর করে প্রয়োগ বন্ধ করা হবে। প্রোগ্রামটি বের হওয়ার আগে যদি আপনার পদক্ষেপ নেওয়া দরকার (যেমন ওয়ার্কিং ডেটা সংরক্ষণ করা) তবে আপনাকে কেবল সাধারণ সুইং ইভেন্ট হ্যান্ডলারগুলি ব্যবহার না করে জেভিএম ইভেন্ট হ্যান্ডলারগুলিতে আলতো চাপতে হবে। উভয়ই "কাজ" করবে তবে EXIT_ON_CLOSE আরও জটিল অ্যাপ্লিকেশনগুলির জন্য সমস্যা সৃষ্টি করবে।
জেমস শেক 11'13

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 করতে পারি, তবে আমি বরং সঠিক জিনিসটি করব।
হান্স-পিটার স্টার

5
System.exit (0) কেবল অপরিশোধিত নয়, এটি মন্দ। সমস্ত ফ্রেম চেক করুন, কল নিষ্পত্তি করুন। যদি এটি ব্যর্থ হয়, একটি ডিবাগার চালান এবং দেখুন কি অ-ডেমন থ্রেডগুলি এখনও বেঁচে আছে।
জেমস শেক

এমনকি জেডিকে-র মধ্যে প্রচুর বাগ রয়েছে যা প্রক্রিয়াটি ছেড়ে দেয়। সুতরাং প্রস্থান করতে +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();
        }
    });

4
মূল শ্রেণীর নামের মতো একটি ভেরিয়েবলের নামকরণের খুব খারাপ স্টাইল Frame...
জিন-ফিলিপ পেলিট

তোমাকে অনেক ধন্যবাদ! এটি অন্যতম সেরা উপায়!
rzaaeeff

9

নিম্নলিখিত প্রোগ্রামটিতে কোড অন্তর্ভুক্ত রয়েছে যা সিস্টেম.এক্সিট () কে স্পষ্টভাবে কল না করে বহিরাগত থ্রেডের অভাবজনিত একটি প্রোগ্রামকে সমাপ্ত করবে। থ্রেড / শ্রোতা / টাইমার / ইত্যাদি ব্যবহার করে অ্যাপ্লিকেশনগুলিতে এই উদাহরণটি প্রয়োগ করার জন্য, উইন্ডো এভেনট ম্যানুয়ালি অ্যাকশনপ্রাপ্ত () এর মধ্যে ম্যানুয়ালি শুরু করার আগে তাদের ক্লিনআপ কোডের জন্য অনুরোধ করা (এবং যদি প্রযোজ্য হয়, অপেক্ষায় থাকে) কেবল ক্লিনআপ কোড সন্নিবেশ করা প্রয়োজন।

যারা দেখানো হয়েছে ঠিক তেমন চলতে সক্ষম কোডটি অনুলিপি / পেস্ট করতে চান তাদের জন্য কিছুটা কুরুচিপূর্ণ তবে অন্যথায় অপ্রাসঙ্গিক মূল পদ্ধতিটি অন্তর্ভুক্ত করা হয়েছে।

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

যদি আমি আপনাকে সঠিকভাবে বুঝতে পারি তবে ব্যবহারকারী বন্ধ বোতামটিতে ক্লিক না করলেও আপনি অ্যাপ্লিকেশনটি বন্ধ করতে চান। আপনার উইন্ডোএভেন্টসটি নিবন্ধ করতে হবে অ্যাডউইন্ডোএলইস্টেনার () অথবা সক্ষমতরসমূহ () এর সাথে যা আপনার প্রয়োজনের জন্য আরও উপযুক্ত হিসাবে সন্ধান করতে পারে।

তারপরে আপনি ইভেন্ট উইন্ডোএভেন্ট () এ কল দিয়ে ইভেন্টটি করতে পারেন। এখানে একটি নমুনা কোড যা একটি জেফ্রেম তৈরি করবে, 5 সেকেন্ড অপেক্ষা করবে এবং ব্যবহারকারীর মিথস্ক্রিয়া ছাড়াই জেফ্রেমটি বন্ধ করবে।

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

}

আপনি দেখতে পাচ্ছেন, প্রক্রিয়া উইন্ডোএভেন্ট () পদ্ধতিটি উইন্ডো ক্লোজড ইভেন্টটিকে বহিস্কারের কারণ হিসাবে আপনার যদি অ্যাপ্লিকেশনটি বন্ধ করার আগে প্রয়োজন হয় তবে কিছু ক্লিন আপ কোড করার জন্য আপনার একটি সুযোগ রয়েছে।


উইন্ডো ক্লোজডকে সিস্টেম.এক্সিট (0) নয়, নিষ্পত্তি কল করতে হবে।
জেমস শেক

2

কটাক্ষপাত ওরাকল ডকুমেন্টেশন

JDK 1.4 থেকে শুরু করে একটি অ্যাপ্লিকেশন সমাপ্ত হয় যদি:

  • কোনও প্রদর্শনযোগ্য এডাব্লুটি বা সুইং উপাদান নেই।
  • নেটিভ ইভেন্টের সারিতে কোনও নেটিভ ইভেন্ট নেই।
  • জাভা ইভেন্টকিউগুলিতে কোনও AWT ইভেন্ট নেই।

কর্নকেসেস:

নথিতে বলা হয়েছে যে কিছু প্যাকেজগুলি মুক্তি না দিয়ে প্রদর্শনযোগ্য উপাদান তৈরি করে। এমন একটি প্রোগ্রাম যা টুলকিট.জেটডিফল্টটুলকিট () কল করে তা শেষ হবে না। উদাহরণ হিসাবে দেওয়া অন্যদের মধ্যে।

এছাড়াও অন্যান্য প্রসেসগুলি এডাব্লুটিটিকে বাঁচিয়ে রাখতে পারে যখন তারা, যে কোনও কারণে, স্থানীয় ইভেন্টের সারিতে ইভেন্ট পাঠাচ্ছে।

এছাড়াও আমি লক্ষ্য করেছি যে কিছু সিস্টেমে অ্যাপ্লিকেশনটি শেষ হওয়ার আগে কয়েক সেকেন্ড সময় নেয়।


0

আমি মনে করি, ধারণাটি এখানে উইন্ডোলিস্টনার - আপনি সেখানে কোনও কোড যুক্ত করতে পারেন যা জিনিসটি বন্ধ হওয়ার আগে আপনি চালাতে চান


0

অন্যান্য মন্তব্যের প্রতিক্রিয়া হিসাবে, DISPOSE_ON_CLOSE অ্যাপ্লিকেশনটি যথাযথভাবে প্রস্থান করে বলে মনে হচ্ছে না - এটি কেবল উইন্ডোটিকেই ধ্বংস করে, তবে অ্যাপ্লিকেশনটি চলতে থাকবে। আপনি যদি অ্যাপ্লিকেশনটি শেষ করতে চান তবে EXIT_ON_CLOSE ব্যবহার করুন।


এই প্রতিক্রিয়াটি জেমস শেকের উত্তরের ঠিক বিপরীত পরামর্শ দেয়। কোনটি সঠিক? (যখন আমি একটি সাধারণ অ্যাপ্লিকেশন দিয়ে পরীক্ষা করি তখন উভয়ই কাজ করে বলে মনে হয় ...)
বা ম্যাপার

আমি এখন এটি কীভাবে পরীক্ষা করেছিলাম তা মনে করতে পারছি না।
জেসিরিস
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.