如何在关闭JFrame时使应用程序后台运行?

4

我在我的Java应用中使用了一个系统托盘。 我想要将GUI隐藏并在后台运行应用程序,但是当用户单击JFrame的关闭按钮时,系统托盘必须保持可用。


1
不要将框架设置为EXIT_ON_CLOSE或在关闭框架时调用System.exit。事件分派线程将继续运行,直到JVM终止。 - MadProgrammer
@MadProgrammer 这就是正确的答案 - 事实上,为什么不把它发布为答案呢? - Adrian
@adrian 因为现在还太早了,我需要再喝一杯茶 :P - MadProgrammer
请查看此相关示例,如何将JFrame隐藏在任务栏的SystemTray中:https://dev59.com/Z2s05IYBdhLWcg3wFN8h - nIcE cOw
4个回答

5
我希望隐藏GUI并在后台运行应用程序,但当用户单击JFrame的关闭按钮时,系统托盘必须保持可用。
设置适当的JFrames setDefaultCloseOperation 方法, JFrame.setDefaultCloseOperation(HIDE_ON_CLOSE),默认情况下在API中实现。
设置用户启动此窗口上的“关闭”操作的默认操作。您必须指定以下选择之一:

DO_NOTHING_ON_CLOSE(在WindowConstants中定义):不做任何操作;要求程序在已注册的WindowListener对象的windowClosing方法中处理操作。

HIDE_ON_CLOSE(在WindowConstants中定义):调用任何已注册的WindowListener对象后自动隐藏框架。

DISPOSE_ON_CLOSE(在WindowConstants中定义):调用任何已注册的WindowListener对象后自动隐藏和释放框架。

EXIT_ON_CLOSE(在JFrame中定义):使用System exit方法退出应用程序。仅在应用程序中使用此选项。

默认情况下,该值设置为HIDE_ON_CLOSE。更改此属性的值会导致触发属性更改事件,属性名称为"defaultCloseOperation"。


1

发布这篇文章作为答案

就像MadProgrammer所说的:

不要将框架设置为EXIT_ON_CLOSE或在关闭框架时调用System.exit。事件分派线程将继续运行,直到JVM被终止。


0

您可以在单独的线程中使用系统托盘。


这是一个非常危险的建议。 - MadProgrammer
1
尽管TrayIcon是一个AWT组件,但它仍然依赖并使用事件分派线程。这可能会导致UI更新在EDT上下文之外执行。最好将非UI处理放在单独的线程中。 - MadProgrammer
他说的是...我刚刚花了一周时间解决由于在EDT之外调用Swing方法而引起的缺陷。如果你不事先注意这个问题,这些问题需要花费很长时间才能追踪到。 - Adrian

-1

如果我没理解错的话,您想要一个后台应用程序,在任何时候都可以查看GUI:

  1. 当你点击窗口的“X”按钮时,可以将框架设置为HIDE_ON_CLOSE

  2. 你需要创建类似于以下代码:

  3. 检查我们是否有两个具有不同操作的按钮

     try {            
         Main_view frame = new Main_view();
         frame.setVisible(true);
    
         if (SystemTray.isSupported()) {
    
             SystemTray tray = SystemTray.getSystemTray();
             TrayIcon trayIcon = null;
    
             //退出按钮监听器
             ActionListener ExitListener = new ActionListener() {
                public void actionPerformed(ActionEvent e) {
                    System.exit(0);
                }
              };
    
              //显示按钮监听器
              ActionListener DisplayListener = new ActionListener() {
                 public void actionPerformed(ActionEvent e) {
                     frame.setVisible(true);
                 }
              };
    
               //右键单击图标时的菜单
               PopupMenu popup = new PopupMenu();
    
               //要显示的按钮
               MenuItem displayButton = new MenuItem("显示");
               MenuItem exitButton = new MenuItem("退出");
    
               //添加之前所做的操作
               exitButton.addActionListener(ExitListener);
               displayButton.addActionListener(DisplayListener);
    
               //添加到弹出菜单中
               popup.add(displayButton);
               popup.add(exitButton);
    
               // URL: MyProject/src/MyGUI/check.png 
               // 在次要任务栏上的小图标
               Image image= ImageIO.read(getClass().getResource("/MyGUI/check.png"));
               trayIcon = new TrayIcon(image, "应用程序名称", popup);
               trayIcon.setImageAutoSize(true);
    
    
               trayIcon.addActionListener(DisplayListener);
               trayIcon.addActionListener(ExitListener);
    
               try {
                    tray.add(trayIcon);
    
                   } catch (AWTException e) {
    
                          System.err.println(e);
                      }
                      // ...
                  } else {
                      // 在你的应用程序中禁用托盘选项或
                      // 执行其他操作
                  }
             } catch (Exception e) {
                 e.printStackTrace();
             }
    

结果

enter image description here


几乎所有的代码都从以下网址提取:https://docs.oracle.com/javase/6/docs/api/java/awt/SystemTray.html 如果您有Java命名约定要分享,请分享,可能会很有用。 - Heterocigoto

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接