Cách đóng JFrame theo chương trình


251

Cách chính xác JFrameđể đóng, giống như khi người dùng nhấn Xnút đóng hoặc nhấn Alt+ F4(trên Windows)?

Tôi có thao tác đóng mặc định của mình được đặt theo cách tôi muốn, thông qua:

setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

Nó thực hiện chính xác những gì tôi muốn với các điều khiển đã nói ở trên. Câu hỏi này không phải là về điều đó.

Điều tôi thực sự muốn làm là khiến GUI hoạt động giống như cách nhấn Xnút đóng sẽ khiến nó hoạt động.

Giả sử tôi đã gia hạn WindowAdaptorvà sau đó thêm một phiên bản bộ điều hợp của tôi làm người nghe thông qua addWindowListener(). Tôi muốn nhìn thấy cùng một chuỗi các cuộc gọi thông qua windowDeactivated(), windowClosing()windowClosed()như có thể xảy ra với các Xnút đóng. Không quá nhiều xé cửa sổ như bảo nó tự xé, để nói.


10
Có gì sai khi sử dụng vứt bỏ? Đó là cách tôi luôn làm.
công việc

1
Vâng, jFrame.dispose () có nên đóng cửa sổ và dọn dẹp mọi thứ không?
Tom Neyland

4
Bởi vì vứt bỏ không phải là 1: 1 tương đương với việc đóng cửa sổ bằng cách nhấp vào [x]?
greenoldman

2
Có một câu hỏi hay, tôi muốn người dùng nhấp vào nút [x] Tôi cung cấp rõ ràng cho phần ghi đè chưa được chỉnh sửa của JFrame để hành động chính xác như thể người dùng đã nhấp vào nút [x] được cung cấp trên hệ điều hành trên cửa sổ JFrame được trang trí cụ thể của hệ điều hành.
peterk

Làm thế nào về điều này.dispatchEvent (wev); thay vì Toolkit.getDefaultToolkit ... Câu trả lời trước đây là những gì câu trả lời được chấp nhận cho thấy.
Jason

Câu trả lời:


320

Nếu bạn muốn GUI hoạt động như thể bạn đã bấm vào Xnút đóng thì bạn cần gửi một sự kiện đóng cửa sổ tới Window. Các ExitActiontừ Bế Một ứng dụng cho phép bạn thêm chức năng này vào một mục trình đơn hoặc bất kỳ thành phần sử dụng Actioncủa một cách dễ dàng.

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

Tôi có cần thêm this.jframe.addWindowListener (new WindowAd CHƯƠNG () {@Override void void window windowClose (WindowEvent e) {e.getWindow (). Dispose ();}}); trước khi gọi điều này? Hay nó cũng sẽ đóng cửa sổ xuống?
mmm

1
"Cách đóng JFrame theo chương trình" - Nếu JFrame.EXIT_ON_CLOSE không được đặt, nó sẽ không đóng. Dù sao, tôi chỉ chỉ ra rằng có thể cần phải thêm vào câu trả lời, vì jframe.setDefaultCloseOperation (WindowConstants.DO_NOTHING_ON_CLOSE); sẽ không thực sự đóng nó bằng cách kích hoạt sự kiện này mặc dù người dùng thường có thể đóng cửa sổ trên X ngay cả khi DO_NOTHING_ON_CLOSE được đặt, nhưng bắn sự kiện này sẽ không xảy ra. Thấy sự khác biệt?
mmm

3
@momomo, không cần chỉ ra gì cả. Câu trả lời này sẽ làm chính xác như OP yêu cầu. Nó sẽ làm bất cứ điều gì nút đóng "X" làm. Tiêu đề của câu hỏi không phải là câu hỏi. OP đặc biệt tuyên bố thao tác đóng mặc định được đặt thành "thoát", do đó, việc "không làm gì" không liên quan vì OP không hỏi về điều đó. Vui lòng xóa tất cả các nhận xét của bạn để bạn không nhầm lẫn người khác đang đọc câu trả lời này, vì câu trả lời đã được đưa ra để trả lời trực tiếp câu hỏi của OP, chứ không phải cách giải thích của bạn về tiêu đề của câu hỏi.
camickr

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

Không quá khó khăn.


38
Nhưng điều đó không gọi người nghe sự kiện.
Bombe

6
Ngoài ra, nếu đây là một nút đóng, quá trình này vẫn chạy trong nền.
Austin A

1
Không phải nếu hoạt động đóng mặc định là trên EXIT_ON_CLOSE hoặc trình nghe nút thực hiện bất kỳ việc đóng tài nguyên cần thiết nào.
Melinda Green

Nó không gọi người nghe.
Stefan Reich

26

Nếu bằng Alt-F4 hoặc X, bạn có nghĩa là "Thoát khỏi ứng dụng ngay lập tức mà không cần quan tâm đến những gì Windows hoặc Chủ đề khác đang chạy", thì System.exit(...)sẽ thực hiện chính xác những gì bạn muốn theo cách rất đột ngột, mạnh mẽ và có thể có vấn đề.

Nếu bằng Alt-F4 hoặc X, bạn có nghĩa là ẩn cửa sổ, thì đó frame.setVisible(false)là cách bạn "đóng" cửa sổ. Cửa sổ sẽ tiếp tục tiêu thụ tài nguyên / bộ nhớ nhưng có thể được hiển thị lại rất nhanh.

Nếu bằng Alt-F4 hoặc X, bạn có nghĩa là ẩn cửa sổ và loại bỏ bất kỳ tài nguyên nào mà nó đang tiêu thụ, thì đó frame.dispose()là cách bạn "đóng" cửa sổ. Nếu khung là cửa sổ hiển thị cuối cùng và không có luồng nào khác không chạy, chương trình sẽ thoát. Nếu bạn hiển thị lại cửa sổ, nó sẽ phải xác định lại tất cả các tài nguyên gốc một lần nữa (bộ đệm đồ họa, tay cầm cửa sổ, v.v.).

dispose()có thể là gần nhất với hành vi mà bạn thực sự muốn. Nếu ứng dụng của bạn có nhiều cửa sổ mở, bạn có muốn Alt-F4 hoặc X thoát khỏi ứng dụng hay chỉ đóng cửa sổ đang hoạt động?

Các Swing Java Tutorial trên Listeners Window có thể giúp làm sáng tỏ mọi thứ cho bạn.


15

Nếu bạn đã làm điều này để đảm bảo người dùng không thể đóng cửa sổ:

frame.setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);

Sau đó, bạn nên thay đổi pullThePlug()phương pháp của bạn để được

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

Tôi thấy đây là cách duy nhất chơi tốt với WindowListenerJFrame.DO_NOTHING_ON_CLOSE.


11

Đây sẽ là lựa chọn của bạn:

System.exit(0); // stop program
frame.dispose(); // close window
frame.setVisible(false); // hide window

8

Thoát khỏi quá trình chạy Java rất dễ dàng, về cơ bản bạn chỉ cần làm hai việc đơn giản:

  1. Gọi phương thức java System.exit(...)tại điểm thoát ứng dụng. Ví dụ: nếu ứng dụng của bạn dựa trên khung, bạn có thể thêm người nghe WindowAdaptervà gọi System.exit(...)bên trong phương thức của nó windowClosing(WindowEvent e).

Lưu ý: bạn phải gọi System.exit(...)nếu không chương trình của bạn có lỗi.

  1. Tránh các ngoại lệ java bất ngờ để đảm bảo phương thức thoát có thể được gọi luôn. Nếu bạn thêm System.exit(...)đúng điểm, nhưng điều đó không có nghĩa là phương thức có thể được gọi luôn, bởi vì các ngoại lệ java không mong muốn có thể ngăn phương thức được gọi.

Điều này liên quan chặt chẽ đến kỹ năng lập trình của bạn.

** Dưới đây là một mẫu đơn giản nhất ( JFramedựa trên) chỉ cho bạn cách gọi phương thức thoát

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

Không chỉ để đóng JFrame mà còn để kích hoạt các sự kiện WindowListener, hãy thử điều này:

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

4

Cách tốt nhất để đóng khung Xoay theo lập trình là làm cho nó hoạt động giống như khi nhấn nút "X". Để làm điều đó, bạn sẽ cần triển khai WindowAd CHƯƠNG phù hợp với nhu cầu của mình và đặt thao tác đóng mặc định của khung thành không làm gì cả (DO_NOTHING_ON_CLOSE).

Khởi tạo khung của bạn như thế này:

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

Bạn có thể đóng khung theo chương trình bằng cách gửi cho nó sự kiện WINDOW_CLOSING, như thế này:

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

Thao tác này sẽ đóng khung giống như nút "X" được nhấn.


4

Nếu bạn thực sự không muốn ứng dụng của mình chấm dứt khi JFrame bị đóng thì

sử dụng : setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);

thay vì : setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

Đây là tóm tắt về giải pháp trông như thế nào,

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

4

Câu trả lời này được đưa ra bởi Alex và tôi muốn giới thiệu nó. Nó làm việc cho tôi và một điều khác, nó đơn giản và đơn giản.

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

1
Giá trị của việc lặp lại một câu trả lời (với hơn 90 phiếu) và nói rằng nó có hiệu quả với bạn là gì? Có lẽ bạn nên xác nhận rằng nó làm việc cho bạn trong một nhận xét về câu trả lời bạn lặp lại?
TT.

Tôi thực sự rất xin lỗi vì điều đó nhưng đôi khi một số người sẽ cảm thấy tự tin hơn khi sử dụng thứ gì đó được đề xuất
Humphrey

Tôi hiểu những gì bạn đang nói, nhưng giả sử mọi người đã sử dụng một câu trả lời có hiệu quả sẽ thêm một câu trả lời nói rằng câu trả lời khác có hiệu quả với tôi. Làm thế nào mà nhìn? Hàng trăm câu trả lời là sự lặp lại của các câu trả lời khác. IMO tốt hơn hết là nêu lên câu trả lời phù hợp với bạn, có thể để lại nhận xét về câu trả lời nếu nó bổ sung bất kỳ giá trị nào.
TT.

Cảm ơn rất nhiều tôi thấy quan điểm của bạn và lần sau đó là những gì tôi sẽ làm để để lại nhận xét. Nhưng nâng cao tôi đã làm.
Humphrey

2
Không, bạn chỉ nên upvote . Đừng để lại bình luận, đừng đăng câu trả lời khác.
dùng202729

3

Ví dụ này cho thấy làm thế nào để nhận ra hoạt động đóng cửa sổ xác nhận.

Cửa sổ có bộ điều hợp Window để chuyển hoạt động đóng mặc định sang EXIT_ON_CLOSEhoặc DO_NOTHING_ON_CLOSEphụ thuộc vào câu trả lời của bạn trong OptionDialog.

Phương pháp closeWindowcủa ConfirmedCloseWindowbắn một sự kiện đóng cửa sổ và có thể được sử dụng bất cứ nơi nào tức là một hành động của một mục trình đơn

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

Dựa trên các câu trả lời đã được cung cấp ở đây, đây là cách tôi thực hiện:

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

// frame stuffs here ...

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

JFrame sẽ đóng sự kiện và sau khi đóng, thoát.


2

Bạn phải chèn cuộc gọi vào hàng đợi tin nhắn AWT để tất cả thời gian diễn ra chính xác, nếu không nó sẽ không gửi đúng chuỗi sự kiện, đặc biệt là trong một chương trình đa luồng. Khi hoàn thành, bạn có thể xử lý chuỗi sự kiện kết quả chính xác như bạn muốn nếu người dùng đã nhấp vào nút [x] cho một JFrame được trang trí cho hệ điều hành.

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

2

Tôi đã thử điều này, viết mã của riêng bạn cho sự kiện formWindowCloses () .

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

Điều này hỏi người dùng liệu anh ta muốn thoát khỏi Khung hoặc Ứng dụng.


1

Đăng những gì trong cơ thể câu hỏi như câu trả lời CW.

Muốn chia sẻ kết quả, chủ yếu bắt nguồn từ liên kết của camickr. Về cơ bản tôi cần ném một WindowEvent.WINDOW_CLOSINGhàng đợi sự kiện của ứng dụng. Dưới đây là tóm tắt về giải pháp trông như thế nào

// 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

Nếu bạn không muốn ứng dụng của mình chấm dứt khi JFrame bị đóng, hãy sử dụng: setDefaultCloseOperation (JFrame.DISPOSE_ON_CLOSE)

thay vì: setDefaultCloseOperation (JFrame.EXIT_ON_CLOSE);

Từ tài liệu:

DO_NOTHING_ON_CLOSE (defined in WindowConstants): Đừng làm gì cả; yêu cầu chương trình xử lý hoạt động trong phương thức windowClose của đối tượng WindowListener đã đăng ký.

HIDE_ON_CLOSE (defined in WindowConstants): Tự động ẩn khung sau khi gọi bất kỳ đối tượng WindowListener đã đăng ký nào.

DISPOSE_ON_CLOSE (defined in WindowConstants): Tự động ẩn và loại bỏ khung sau khi gọi bất kỳ đối tượng WindowListener đã đăng ký nào.

EXIT_ON_CLOSE (defined in JFrame): Thoát khỏi ứng dụng bằng phương thức Thoát hệ thống. Chỉ sử dụng điều này trong các ứng dụng.

vẫn có thể hữu ích: Bạn có thể sử dụng setVisible(false)trên JFrame của mình nếu bạn muốn hiển thị lại cùng một khung. Nếu không hãy gọi dispose()để loại bỏ tất cả các tài nguyên màn hình gốc.

sao chép từ Peter Lang

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


0
 setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);

Điều này sẽ hoạt động cùng vớisetVisible(false) .setVisible(false); .setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
Abhijeet
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.