【问题标题】:How to programmatically close a JFrame如何以编程方式关闭 JFrame
【发布时间】:2010-11-17 02:54:19
【问题描述】:

关闭JFrame的正确方法是什么,就像用户点击了X关闭按钮,或者按下了Alt+F4 (在 Windows 上)?

我有我的默认关闭操作设置我想要的方式,通过:

setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

它完全符合我对上述控件的要求。这个问题不是关于那个的。

我真正想做的是让 GUI 的行为方式与按下 X 关闭按钮的行为方式相同。

假设我要扩展WindowAdaptor,然后通过addWindowListener() 添加我的适配器实例作为侦听器。我希望通过windowDeactivated()windowClosing()windowClosed() 看到与X 关闭按钮相同的调用序列。与其说是撕毁窗户,不如说是告诉它自己撕毁。

【问题讨论】:

  • 是的,jFrame.dispose() 应该关闭窗口并清理所有内容?
  • 因为 dispose 不是 1:1 相当于点击 [x] 关闭窗口?
  • 是的好问题,我希望用户单击我明确提供的未修饰的 JFrame 覆盖上的 [x] 按钮,以 完全 像用户单击一样操作操作系统特定的装饰 JFrame 窗口上的操作系统提供的 [x] 按钮。
  • this.dispatchEvent(wev); 怎么样?而不是 Toolkit.getDefaultToolkit... 前者是公认的答案所暗示的。

标签: java swing jframe


【解决方案1】:

退出Java运行进程非常简单,基本上只需要做两件简单的事情:

  1. 在应用程序的退出点调用java方法System.exit(...)。 例如,如果您的应用程序是基于框架的,您可以添加侦听器WindowAdapter 并在其方法windowClosing(WindowEvent e) 中调用System.exit(...)

注意:您必须调用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);
   }
}

【讨论】:

    【解决方案2】:

    以下是您的选择:

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

    【讨论】:

      【解决方案3】:

      我已经尝试过了,为 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);
          }
      }    
      

      这会询问用户是否要退出框架或应用程序。

      【讨论】:

        【解决方案4】:

        这个答案是由 Alex 给出的,我想推荐它。它对我有用,另一件事是简单明了。

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

        【讨论】:

        • 重复一个答案(+90 票)并告诉它对你有用有什么价值?也许您应该在对您重复的答案的评论中确认它对您有用?
        • 对此我感到非常抱歉,但有时有些人会觉得使用推荐的东西更有信心
        • 我明白你在说什么,但假设每个使用有效答案的人都添加了一个答案,说另一个答案对我有用。那看起来怎么样?数百个答案是其他答案的重复。 IMO 最好对对您有用的答案进行投票,如果它增加了任何价值,也许可以对答案发表评论。
        • 非常感谢,我明白了你的观点,下次我会这样做以发表评论。但是我投票赞成。
        • 不,你应该只是投票。不要发表评论,不要发布其他答案。
        【解决方案5】:

        如果你真的不希望你的应用程序在 JFrame 关闭时终止,那么

        使用:setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);

        而不是:setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        这是解决方案的概要,

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

        【讨论】:

          【解决方案6】:

          如果您希望 GUI 的行为就像您单击了 X 关闭按钮,那么您需要向 Window 发送一个窗口关闭事件。来自Closing An ApplicationExitAction 允许您将此功能添加到菜单项或任何使用Actions 的组件中。

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

          【讨论】:

          • 是否需要添加 this.jframe.addWindowListener(new WindowAdapter() { @Override public void windowClosing( WindowEvent e ) { e.getWindow().dispose(); } });在调用这个之前?或者它也会关闭窗口?
          • "如何以编程方式关闭 JFrame" - 如果未设置 JFrame.EXIT_ON_CLOSE,它将不会关闭。无论如何,我只是指出可能需要添加到答案中,因为 jframe.setDefaultCloseOperation(WindowConstants.DO_NOTHING_ON_CLOSE);尽管设置了 DO_NOTHING_ON_CLOSE 用户通常能够关闭 X 上的窗口,但实际上不会通过触发此事件来关闭它,但不会触发此事件。看出区别了吗?
          • @momomo,没有必要指出任何事情。这个答案将完全按照 OP 的要求进行。它将执行“X”关闭按钮所做的任何事情。问题的标题不是问题。 OP 明确表示默认关闭操作设置为“退出”,因此“什么都不做”的作用无关紧要,因为 OP 没有询问这一点。请删除您所有的 cmets,以免其他人在阅读此答案时感到困惑,因为给出的答案是为了直接回答 OP 的问题,而不是您对问题标题的解释。
          • 这个答案对于任何不平凡的场景都是无用的,因为在任何不平凡的场景中,我想要以编程方式关闭框架的原因正是因为我已经处理了“关闭”事件,采取了各种行动来确定框架是否应该关闭,已经确定框架确实应该关闭,现在正试图真正关闭它。因此,再次调用“关闭”事件将导致无限递归。
          【解决方案7】:

          如果您不希望应用程序在 JFrame 关闭时终止, 采用: setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE)

          而不是: setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

          来自文档:

          DO_NOTHING_ON_CLOSE (defined in WindowConstants):什么都别做;要求程序在注册的WindowListener对象的windowClosing方法中处理操作。

          HIDE_ON_CLOSE (defined in WindowConstants): 调用任何注册的 WindowListener 对象后自动隐藏框架。

          DISPOSE_ON_CLOSE (defined in WindowConstants): 调用任何注册的 WindowListener 对象后自动隐藏和释放框架。

          EXIT_ON_CLOSE (defined in JFrame):使用系统退出方法退出应用程序。仅在应用程序中使用它。

          可能仍然有用: 如果要再次显示同一帧,可以在 JFrame 上使用setVisible(false)。 否则调用dispose() 删除所有原生屏幕资源。

          抄自彼得朗

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

          【讨论】:

            【解决方案8】:

            不仅要关闭 JFrame,还要触发 WindowListener 事件,试试这个:

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

            【讨论】:

              【解决方案9】:

              以编程方式关闭 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”按钮一样关闭框架。

              【讨论】:

                【解决方案10】:

                将问题正文中的内容发布为 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();
                

                【讨论】:

                  【解决方案11】:

                  根据这里已经提供的答案,这是我实现它的方式:

                  JFrame frame= new JFrame()
                  frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                  
                  // frame stuffs here ...
                  
                  frame.dispatchEvent(new WindowEvent(frame, WindowEvent.WINDOW_CLOSING));
                  

                  JFrame 让事件关闭,并在关闭时退出。

                  【讨论】:

                    【解决方案12】:

                    如果 Alt-F4 或 X 的意思是“立即退出应用程序而不考虑正在运行的其他 Windows 或线程”,那么 System.exit(...)完全非常突然地执行您想要的操作,蛮力,并且可能有问题的时尚。

                    如果按 Alt-F4 或 X 表示隐藏窗口,那么 frame.setVisible(false) 就是您“关闭”窗口的方式。该窗口将继续消耗资源/内存,但可以很快再次可见。

                    如果您使用 Alt-F4 或 X 表示隐藏窗口并处理它正在消耗的任何资源,那么 frame.dispose() 就是您“关闭”窗口的方式。如果该框架是最后一个可见窗口并且没有其他非守护线程在运行,则程序将退出。如果您再次显示该窗口,它将不得不再次重新初始化所有本机资源(图形缓冲区、窗口句柄等)。

                    dispose() 可能最接近您真正想要的行为。如果您的应用打开了多个窗口,您希望 Alt-F4 或 X 退出应用还是只关闭活动窗口?

                    Java Swing Tutorial on Window Listeners 可能会帮助您澄清事情。

                    【讨论】:

                      【解决方案13】:

                      您必须将调用插入到 AWT 消息队列中,以便所有时间都正确发生,否则它将无法调度正确的事件序列,尤其是在多线程程序中。完成此操作后,您可以完全按照用户单击 OS 提供的修饰 JFrame 的 [x] 按钮来处理生成的事件序列。

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

                      【讨论】:

                        【解决方案14】:

                        这个例子展示了如何实现确认窗口关闭操作。

                        窗口有一个窗口适配器,它根据您在OptionDialog 中的回答将默认关闭操作切换为EXIT_ON_CLOSEDO_NOTHING_ON_CLOSE

                        ConfirmedCloseWindow 的方法 closeWindow 触发关闭窗口事件,并且可以在任何地方使用,即作为菜单项的操作

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

                        【讨论】:

                          【解决方案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 完美搭配的唯一方式。

                          【讨论】:

                            【解决方案16】:
                            setVisible(false); //you can't see me!
                            dispose(); //Destroy the JFrame object
                            

                            不太难。

                            【讨论】:

                            • 但这不会调用事件监听器。
                            • 另外,如果这将是一个关闭按钮,该进程也会在后台运行。
                            • 如果默认关闭操作在 EXIT_ON_CLOSE 上或按钮侦听器执行任何需要的资源关闭,则不会。
                            • 它不调用监听器。
                            • 据我观察,调用dispose() 实际上会导致发出“停用”和“关闭”侦听器事件。所以,我不知道上面的评论者在抱怨什么。
                            【解决方案17】:
                             setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
                            

                            【讨论】:

                            • 这将与 setVisible(false) .setVisible(false); .setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE); 一起使用
                            猜你喜欢
                            • 2011-07-15
                            • 2015-11-26
                            • 2020-07-08
                            • 2013-07-04
                            • 2016-03-08
                            • 1970-01-01
                            • 1970-01-01
                            • 1970-01-01
                            相关资源
                            最近更新 更多