วิธีปิด JFrame โดยทางโปรแกรม


251

วิธีที่ถูกต้องในการJFrameปิดคืออะไรเหมือนกับว่าผู้ใช้กดXปุ่มปิดหรือกดAlt+ F4(บน Windows)

ฉันมีการดำเนินการปิดเริ่มต้นของฉันตั้งค่าตามที่ฉันต้องการผ่าน:

setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

มันทำสิ่งที่ฉันต้องการอย่างแน่นอนด้วยการควบคุมข้างต้น คำถามนี้ไม่เกี่ยวกับเรื่องนั้น

สิ่งที่ฉันต้องการทำจริงๆคือทำให้ GUI ทำงานในลักษณะเดียวกับที่การกดปุ่มXปิดจะทำให้มันทำงาน

สมมติว่าฉันกำลังจะขยายและเพิ่มตัวอย่างของอะแดปเตอร์ของฉันเป็นผู้ฟังผ่านทางWindowAdaptor addWindowListener()ผมอยากจะเห็นลำดับเดียวกันของการโทรผ่านwindowDeactivated(), windowClosing()และwindowClosed()ตามที่จะเกิดขึ้นกับXปุ่มปิด ไม่ได้ทำให้หน้าต่างฉีกขาดมากนักเหมือนกับบอกให้มันฉีกตัวเองดังนั้นพูด


10
เกิดอะไรขึ้นกับการใช้งานการกำจัด? นั่นคือวิธีที่ฉันทำมันมาตลอด
งาน

1
ใช่ jFrame.dispose () ควรปิดหน้าต่างและทำความสะอาดทุกอย่างหรือไม่
Tom Neyland

4
เพราะการกำจัดไม่เท่ากับ 1: 1 เทียบเท่ากับการปิดหน้าต่างโดยคลิกที่ [x]?
greenoldman

2
ใช่คำถามที่ดีฉันต้องการให้ผู้ใช้คลิกที่ปุ่ม [x] ฉันระบุอย่างชัดเจนเกี่ยวกับการแทนที่ของ JFrame เพื่อทำหน้าที่เหมือนกับว่าผู้ใช้คลิกปุ่ม OS ที่ให้มา [x] บนหน้าต่าง JFrame ที่ได้รับการตกแต่งเฉพาะระบบปฏิบัติการ
peterk

วิธีการเกี่ยวกับ this.dispatchEvent (wev); แทนที่จะเป็น Toolkit.getDefaultToolkit ... คำตอบเดิมคือสิ่งที่คำตอบที่ยอมรับได้แสดงให้เห็น
Jason

คำตอบ:


320

หากคุณต้องการ GUI ที่จะประพฤติตัวเป็นถ้าคุณคลิกที่ปุ่มปิดแล้วคุณจะต้องส่งเหตุการณ์ปิดหน้าต่างไปX จากการปิดการประยุกต์ช่วยให้คุณสามารถเพิ่มฟังก์ชันการทำงานนี้ไปยังรายการเมนูหรือองค์ประกอบใด ๆ ที่ใช้s ได้อย่างง่ายดายWindowExitActionAction

frame.dispatchEvent(new WindowEvent(frame, WindowEvent.WINDOW_CLOSING));

ฉันต้องเพิ่มสิ่งนี้หรือไม่ ก่อนที่จะเรียกสิ่งนี้ หรือมันจะปิดหน้าต่างเช่นกัน?
mmm

1
"วิธีการปิด JFrame โดยทางโปรแกรม" - หาก JFrame.EXIT_ON_CLOSE ไม่ได้ตั้งค่ามันจะไม่ปิด อย่างไรก็ตามฉันเพิ่งชี้ให้เห็นว่าอาจจำเป็นต้องเพิ่มคำตอบเนื่องจาก jframe.setDefaultCloseOperation (WindowConstants.DO_NOTHING_ON_CLOSE); จะไม่ปิดโดยเรียกเหตุการณ์นี้แม้ว่าผู้ใช้จะสามารถปิดหน้าต่างใน X ได้แม้ว่าจะมีการตั้งค่า DO_NOTHING_ON_CLOSE แต่การยิงเหตุการณ์นี้จะไม่เกิดขึ้นก็ตาม ดูความแตกต่าง?
mmm

3
@ โมโมโมะไม่จำเป็นต้องชี้ให้เห็นอะไรเลย คำตอบนี้จะทำตรงตาม OP ถาม มันจะทำทุกอย่างที่ปุ่ม "X" ปิด ชื่อของคำถามไม่ใช่คำถาม OP ระบุไว้เป็นการเฉพาะว่าการปิดเริ่มต้นถูกตั้งค่าเป็น "exit" ดังนั้นสิ่งที่ "ไม่ทำอะไร" จะไม่เกี่ยวข้องเนื่องจาก OP ไม่ได้ถามเกี่ยวกับสิ่งนั้น โปรดลบความคิดเห็นทั้งหมดของคุณเพื่อที่คุณจะได้ไม่สับสนคนอื่นที่อ่านคำตอบนี้เนื่องจากได้รับคำตอบให้ตอบคำถามของ OP โดยตรงไม่ใช่การตีความในส่วนหัวของคำถาม
camickr

131
setVisible(false); //you can't see me!
dispose(); //Destroy the JFrame object

ไม่ยุ่งยากเกินไป


38
แต่นั่นไม่ได้เรียกผู้ฟังเหตุการณ์
Bombe

6
นอกจากนี้หากเป็นปุ่มปิดกระบวนการจะทำงานในพื้นหลังด้วย
Austin A

1
ไม่ใช่หากการดำเนินการปิดเริ่มต้นอยู่ใน EXIT_ON_CLOSE หรือฟังปุ่มดำเนินการปิดทรัพยากรที่จำเป็น
Melinda Green

มันไม่ได้เรียกผู้ฟัง
Stefan Reich

26

ถ้าโดย Alt-F4 หรือ X คุณหมายถึง "ออกจากโปรแกรมทันทีโดยไม่คำนึงถึงสิ่งอื่น ๆ Windows หรือหัวข้อที่กำลังทำงานอยู่" จากนั้นSystem.exit(...)จะทำว่าสิ่งที่คุณต้องการในทันทีทันใดมากแรงเดรัจฉานและแฟชั่นอาจจะมีปัญหา

หากใช้ Alt-F4 หรือ X คุณหมายถึงซ่อนหน้าต่างแสดงframe.setVisible(false)ว่าคุณปิดหน้าต่างอย่างไร หน้าต่างจะใช้ทรัพยากร / หน่วยความจำต่อไป แต่สามารถมองเห็นได้อีกครั้งอย่างรวดเร็ว

หากใช้ Alt-F4 หรือ X คุณหมายถึงซ่อนหน้าต่างและกำจัดทรัพยากรใด ๆ ที่กำลังใช้งานframe.dispose()อยู่นั่นคือวิธีที่คุณ "ปิด" หน้าต่าง หากเฟรมเป็นหน้าต่างสุดท้ายที่มองเห็นได้และไม่มีเธรดที่ไม่ใช่ daemon อื่น ๆ กำลังทำงานอยู่โปรแกรมจะออกจากโปรแกรม หากคุณแสดงหน้าต่างอีกครั้งจะต้องกำหนดค่าเริ่มต้นของทรัพยากรดั้งเดิมทั้งหมดอีกครั้ง (บัฟเฟอร์กราฟิกตัวจัดการหน้าต่าง ฯลฯ )

dispose()อาจใกล้เคียงกับพฤติกรรมที่คุณต้องการจริงๆ หากแอปของคุณมีหลายหน้าต่างที่เปิดอยู่คุณต้องการให้ Alt-F4 หรือ X ปิดแอพหรือปิดหน้าต่างที่ใช้งานอยู่หรือไม่?

Java Swing กวดวิชาในฟังหน้าต่างอาจช่วยชี้แจงสิ่งสำหรับคุณ


15

หากคุณทำสิ่งนี้เพื่อให้แน่ใจว่าผู้ใช้ไม่สามารถปิดหน้าต่างได้:

frame.setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);

จากนั้นคุณควรเปลี่ยนpullThePlug()วิธีการของคุณเป็น

public void pullThePlug() {
    // this will make sure WindowListener.windowClosing() et al. will be called.
    WindowEvent wev = new WindowEvent(this, WindowEvent.WINDOW_CLOSING);
    Toolkit.getDefaultToolkit().getSystemEventQueue().postEvent(wev);

    // this will hide and dispose the frame, so that the application quits by
    // itself if there is nothing else around. 
    setVisible(false);
    dispose();
    // if you have other similar frames around, you should dispose them, too.

    // finally, call this to really exit. 
    // i/o libraries such as WiiRemoteJ need this. 
    // also, this is what swing does for JFrame.EXIT_ON_CLOSE
    System.exit(0); 
}

ฉันพบนี้จะเป็นวิธีเดียวที่เล่นดีกับและWindowListenerJFrame.DO_NOTHING_ON_CLOSE



8

การออกจากกระบวนการเรียกใช้ Java นั้นง่ายมากโดยทั่วไปคุณต้องทำสองสิ่งง่ายๆ:

  1. เรียกวิธีการจาวาSystem.exit(...)ที่จุดออกจากแอปพลิเคชัน ตัวอย่างเช่นถ้าใบสมัครของคุณตามกรอบคุณสามารถเพิ่มฟังWindowAdapterและและโทรภายในวิธีการของSystem.exit(...)windowClosing(WindowEvent e)

หมายเหตุ: คุณต้องโทรSystem.exit(...)มิฉะนั้นโปรแกรมของคุณมีข้อผิดพลาด

  1. หลีกเลี่ยงข้อยกเว้น java ที่ไม่คาดคิดเพื่อให้แน่ใจว่าสามารถเรียกเมธอด exit ได้เสมอ หากคุณเพิ่มSystem.exit(...)ในจุดที่ถูกต้อง แต่ไม่ได้หมายความว่าสามารถเรียกวิธีการได้เสมอเนื่องจากข้อยกเว้น java ที่ไม่คาดคิดอาจป้องกันวิธีการที่เรียก

สิ่งนี้เกี่ยวข้องอย่างยิ่งกับทักษะการเขียนโปรแกรมของคุณ

** ต่อไปนี้เป็นตัวอย่างที่ง่ายที่สุด ( JFrameตาม) ซึ่งแสดงวิธีการโทรออก

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

public class ExitApp extends JFrame
{
   public ExitApp()
   {
      addWindowListener(new WindowAdapter()
      {
         public void windowClosing(WindowEvent e)
         {
           dispose();
           System.exit(0); //calling the method is a must
         }
      });
   }

   public static void main(String[] args)
   {
      ExitApp app=new ExitApp();
      app.setBounds(133,100,532,400);
      app.setVisible(true);
   }
}

7

ไม่เพียง แต่จะปิด JFrame แต่ยังเพื่อทริกเกอร์เหตุการณ์ WindowListener ให้ลองทำสิ่งนี้:

myFrame.dispatchEvent(new WindowEvent(myFrame, WindowEvent.WINDOW_CLOSING));

4

วิธีที่ดีที่สุดในการปิดเฟรม Swing โดยทางโปรแกรมคือการทำให้มันทำงานเหมือนเมื่อกดปุ่ม "X" ในการทำเช่นนั้นคุณจะต้องใช้ WindowAdapter ที่เหมาะสมกับความต้องการของคุณและตั้งค่าการปิดเฟรมเริ่มต้นเพื่อไม่ทำอะไรเลย (DO_NOTHING_ON_CLOSE)

เริ่มต้นเฟรมของคุณเช่นนี้:

private WindowAdapter windowAdapter = null;

private void initFrame() {

    this.windowAdapter = new WindowAdapter() {
        // WINDOW_CLOSING event handler
        @Override
        public void windowClosing(WindowEvent e) {
            super.windowClosing(e);
            // You can still stop closing if you want to
            int res = JOptionPane.showConfirmDialog(ClosableFrame.this, "Are you sure you want to close?", "Close?", JOptionPane.YES_NO_OPTION);
            if ( res == 0 ) {
                // dispose method issues the WINDOW_CLOSED event
                ClosableFrame.this.dispose();
            }
        }

        // WINDOW_CLOSED event handler
        @Override
        public void windowClosed(WindowEvent e) {
            super.windowClosed(e);
            // Close application if you want to with System.exit(0)
            // but don't forget to dispose of all resources 
            // like child frames, threads, ...
            // System.exit(0);
        }
    };

    // when you press "X" the WINDOW_CLOSING event is called but that is it
    // nothing else happens
    this.setDefaultCloseOperation(ClosableFrame.DO_NOTHING_ON_CLOSE);
    // don't forget this
    this.addWindowListener(this.windowAdapter);
}

คุณสามารถปิดเฟรมโดยทางโปรแกรมโดยส่งกิจกรรม WINDOW_CLOSING เช่นนี้:

WindowEvent closingEvent = new WindowEvent(targetFrame, WindowEvent.WINDOW_CLOSING);
Toolkit.getDefaultToolkit().getSystemEventQueue().postEvent(closingEvent);

นี่จะเป็นการปิดเฟรมเหมือนที่กดปุ่ม "X"


4

หากคุณไม่ต้องการให้แอปพลิเคชันของคุณปิดเมื่อ JFrame ถูกปิดไปแล้ว

ใช้: setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);

แทน : setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

ต่อไปนี้เป็นบทสรุปของลักษณะที่โซลูชันดังกล่าว

 myFrame.dispatchEvent(new WindowEvent(myFrame, WindowEvent.WINDOW_CLOSING));

4

Alex ได้รับคำตอบนี้และฉันอยากจะแนะนำ มันใช้งานได้สำหรับฉันและอีกอย่างมันตรงไปตรงมาและเรียบง่ายมาก

setVisible(false); //you can't see me!
dispose(); //Destroy the JFrame object

1
มูลค่าของการทำซ้ำคำตอบ (ด้วยคะแนน +90) และบอกว่ามันทำงานได้สำหรับคุณคืออะไร? บางทีคุณควรยืนยันว่ามันใช้งานได้กับคุณในความคิดเห็นเกี่ยวกับคำตอบที่คุณทำซ้ำ?
TT

ฉันเสียใจจริง ๆ สำหรับสิ่งนั้น แต่บางครั้งบางคนอาจรู้สึกมั่นใจมากขึ้นเมื่อใช้สิ่งที่แนะนำ
Humphrey

ฉันเข้าใจสิ่งที่คุณพูด แต่สมมติว่าทุกคนที่ใช้คำตอบที่ได้ผลนั้นเพิ่มคำตอบที่บอกว่าคำตอบอื่นนั้นเหมาะกับฉัน มันจะมีลักษณะอย่างไร หลายร้อยคำตอบเป็นการทำซ้ำคำตอบอื่น ๆ IMO จะเป็นการดีกว่าที่จะถอนคำตอบที่เหมาะกับคุณออกไปอาจแสดงความคิดเห็นในคำตอบหากมันเพิ่มคุณค่าใด ๆ
TT

ขอบคุณมากที่ฉันเห็นจุดของคุณและครั้งต่อไปนั่นคือสิ่งที่ฉันจะทำเพื่อแสดงความคิดเห็น แต่การลุกขึ้นสู้ฉัน
Humphrey

2
ไม่คุณควรโหวตเท่านั้น อย่าแสดงความคิดเห็นอย่าโพสต์คำตอบอื่น
user202729

3

ตัวอย่างนี้แสดงวิธีการตระหนักถึงการดำเนินการปิดหน้าต่างที่ยืนยัน

หน้าต่างมีอะแดปเตอร์สวิทช์หน้าต่างซึ่งการดำเนินงานใกล้เริ่มต้นEXIT_ON_CLOSEหรือขึ้นอยู่กับคำตอบของคุณในDO_NOTHING_ON_CLOSEOptionDialog

วิธีcloseWindowการConfirmedCloseWindowยิงเหตุการณ์หน้าต่างปิดและสามารถใช้งานได้ทุกที่เช่นการกระทำของรายการเมนู

public class WindowConfirmedCloseAdapter extends WindowAdapter {

    public void windowClosing(WindowEvent e) {

        Object options[] = {"Yes", "No"};

        int close = JOptionPane.showOptionDialog(e.getComponent(),
                "Really want to close this application?\n", "Attention",
                JOptionPane.YES_NO_OPTION,
                JOptionPane.INFORMATION_MESSAGE,
                null,
                options,
                null);

        if(close == JOptionPane.YES_OPTION) {
           ((JFrame)e.getSource()).setDefaultCloseOperation(
                   JFrame.EXIT_ON_CLOSE);
        } else {
           ((JFrame)e.getSource()).setDefaultCloseOperation(
                   JFrame.DO_NOTHING_ON_CLOSE);
        }
    }
}

public class ConfirmedCloseWindow extends JFrame {

    public ConfirmedCloseWindow() {

        addWindowListener(new WindowConfirmedCloseAdapter());
    }

    private void closeWindow() {
        processWindowEvent(new WindowEvent(this, WindowEvent.WINDOW_CLOSING));
    }
}

3

จากคำตอบที่มีให้ที่นี่นี่คือวิธีที่ฉันใช้มัน:

JFrame frame= new JFrame()
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

// frame stuffs here ...

frame.dispatchEvent(new WindowEvent(frame, WindowEvent.WINDOW_CLOSING));

JFrame ทำให้เหตุการณ์ปิดและเมื่อปิดออก


2

คุณต้องแทรกการโทรในคิวข้อความ AWT เพื่อให้เวลาทั้งหมดเกิดขึ้นอย่างถูกต้องมิฉะนั้นจะไม่ส่งลำดับเหตุการณ์ที่ถูกต้องโดยเฉพาะในโปรแกรมแบบมัลติเธรด เมื่อทำสิ่งนี้เสร็จคุณอาจจัดการลำดับเหตุการณ์ที่เกิดขึ้นอย่างที่คุณต้องการหากผู้ใช้คลิกปุ่ม [x] สำหรับระบบปฏิบัติการที่ได้รับการตกแต่ง JFrame

public void closeWindow()
{
    if(awtWindow_ != null) {
        EventQueue.invokeLater(new Runnable() {
            public void run() {
                awtWindow_.dispatchEvent(new WindowEvent(awtWindow_, WindowEvent.WINDOW_CLOSING));
            }
        });
    }
}

2

ฉันได้พยายามนี้เขียนรหัสของคุณเองสำหรับformWindowClosing ()เหตุการณ์

 private void formWindowClosing(java.awt.event.WindowEvent evt) {                                   
    int selectedOption = JOptionPane.showConfirmDialog(null,
            "Do you want to exit?",
            "FrameToClose",
            JOptionPane.YES_NO_OPTION);
    if (selectedOption == JOptionPane.YES_OPTION) {
        setVisible(false);
        dispose();
    } else {
        setDefaultCloseOperation(javax.swing.WindowConstants.DO_NOTHING_ON_CLOSE);
    }
}    

สิ่งนี้จะถามผู้ใช้ว่าเขาต้องการออกจาก Frame หรือแอปพลิเคชันหรือไม่


1

การโพสต์สิ่งที่อยู่ในเนื้อหาคำถามเป็นคำตอบ CW

ต้องการแบ่งปันผลลัพธ์ส่วนใหญ่มาจากการติดตามลิงก์ของ camickr โดยทั่วไปฉันต้องโยนWindowEvent.WINDOW_CLOSINGที่คิวกิจกรรมของแอปพลิเคชัน ต่อไปนี้เป็นบทสรุปของสิ่งที่โซลูชันดูเหมือน

// closing down the window makes sense as a method, so here are
// the salient parts of what happens with the JFrame extending class ..

    public class FooWindow extends JFrame {
        public FooWindow() {
            setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            setBounds(5, 5, 400, 300);  // yeah yeah, this is an example ;P
            setVisible(true);
        }
        public void pullThePlug() {
                WindowEvent wev = new WindowEvent(this, WindowEvent.WINDOW_CLOSING);
                Toolkit.getDefaultToolkit().getSystemEventQueue().postEvent(wev);
        }
    }

// Here's how that would be employed from elsewhere -

    // someplace the window gets created ..
    FooWindow fooey = new FooWindow();
    ...
    // and someplace else, you can close it thusly
    fooey.pullThePlug();

1

หากคุณไม่ต้องการให้แอปพลิเคชันของคุณปิดเมื่อปิด JFrame ให้ใช้: setDefaultCloseOperation (JFrame.DISPOSE_ON_CLOSE)

แทน: setDefaultCloseOperation (JFrame.EXIT_ON_CLOSE);

จากเอกสาร:

DO_NOTHING_ON_CLOSE (defined in WindowConstants): อย่าทำอะไรเลย ต้องการให้โปรแกรมจัดการการดำเนินการในหน้าต่างวิธีการปิดของวัตถุ WindowListener ที่ลงทะเบียน

HIDE_ON_CLOSE (defined in WindowConstants): ซ่อนเฟรมโดยอัตโนมัติหลังจากเรียกใช้วัตถุ WindowListener ที่ลงทะเบียนแล้ว

DISPOSE_ON_CLOSE (defined in WindowConstants): ซ่อนและกำจัดเฟรมโดยอัตโนมัติหลังจากเรียกใช้ออบเจ็กต์ WindowListener ที่ลงทะเบียนแล้วใด ๆ

EXIT_ON_CLOSE (defined in JFrame): ออกจากแอปพลิเคชันโดยใช้วิธีการออกจากระบบ ใช้สิ่งนี้ในแอปพลิเคชันเท่านั้น

อาจยังมีประโยชน์: คุณสามารถใช้setVisible(false)กับ JFrame ของคุณหากคุณต้องการแสดงเฟรมเดียวกันอีกครั้ง มิฉะนั้นโทรdispose()เพื่อลบทรัพยากรหน้าจอพื้นเมืองทั้งหมด

คัดลอกมาจาก Peter Lang

https://stackoverflow.com/a/1944474/3782247


0
 setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);

สิ่งนี้จะทำงานร่วมกับsetVisible(false) .setVisible(false); .setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
Abhijeet
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.