1

我正在使用以下方法来显示框架:

public static void createImage(final String url, final String file, final String filetype) {
        UIUtils.setPreferredLookAndFeel();
        NativeInterface.open();
        SwingUtilities.invokeLater(new Runnable() {

            @SuppressWarnings("deprecation")
            @Override
            public void run() {

                frame = new JFrame();
                WebsiteThumbnailCreator ex = new WebsiteThumbnailCreator(url, file, filetype);

                frame.getContentPane().add(ex, BorderLayout.CENTER);
                frame.setSize(FRAMESIZE);
                frame.setLocationByPlatform(true);
                frame.setVisible(true);
                frame.hide();
            }

        });

        NativeInterface.runEventPump(); 
  }

然后我做一些计算,然后,我想再次处理框架:

try {
   ImageIO.write(rendered, filetype, new File(file + "." + filetype));
   frame.dispose();
   logger.trace("Tried to dispose the frame");
} catch (IOException e) {
   logger.fatal(e.getMessage());
} finally {
    logger.debug("Try to dispose the frame");
    frame.dispose();
}

我可以看到日志消息,但是虚拟机仍在运行。我也想终止它。我究竟做错了什么?

似乎仍然在运行一个非守护线程,但我不明白为什么:

在此处输入图像描述

4

3 回答 3

2

您没有设置 JFrame 的默认关闭操作,它默认为JFrame.HIDE_ON_CLOSE.

添加到您的 JFrame 设置代码:

frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

如果您的 JFrame 是您的应用程序,并且您想在 JFrame 关闭时退出所有内容,或者

frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);

如果您的 JFrame 不是整个应用程序并且您想停止 Swing 线程但继续处理。

有关这方面的更多信息,请查看JFrame API

编辑:
关于您的评论,

@HovercraftFullOfEels 好吧,如果你说的是对的,为什么我的框架在这​​段代码中消失了: public static void frameTest() throws InterruptedException { final JFrame jf = new JFrame("Hello World"); jf.setBounds(100, 100, 400, 400); jf.setVisible(true); 线程.sleep(8000); SwingUtilities.invokeLater(new Runnable() { public void run() { // TODO 自动生成的方法存根 jf.dispose(); } }); }

我翻译成:

public static void frameTest() throws InterruptedException {
  final JFrame jf = new JFrame("Hello World");
  jf.setBounds(100, 100, 400, 400);
  jf.setVisible(true);
  Thread.sleep(8000);
  SwingUtilities.invokeLater(new Runnable() {
     public void run() {
        jf.dispose();
     }
  });
}

仅当没有更多非守护线程时才退出。如果你给它一个非守护线程,它会继续运行。例如,

public static void main(String[] args) {
  new Thread(new Runnable() {
     public void run() {
        for (int i = 0; i < 30; i++) {
           System.out.println("i := " + i);
           try {
              Thread.sleep(1000);
           } catch (InterruptedException e) {
              e.printStackTrace();
           }
        }
     }
  }).start();
  try {
     frameTest();
  } catch (InterruptedException e) {
     e.printStackTrace();
  }
}

您的代码将在此示例中继续运行。

于 2012-05-02T21:18:34.577 回答
2

如果你打电话

try {
   ImageIO.write(rendered, filetype, new File(file + "." + filetype));
   frame.dispose();
   logger.trace("Tried to dispose the frame");
} catch (IOException e) {
   logger.fatal(e.getMessage());
} finally {
    logger.debug("Try to dispose the frame");
    frame.dispose();
}

然后代码将被执行,但是

1) 仅当在 EDT 上完成时,否则...... EDT 之外Top-Level Containers的内容会粘在屏幕上

或者

2)Top-Level Containers错过的方法finalize(),然后永远不会GC'ed(基于来自Windows NT/2000那个活着的资源的一些限制......),然后来自控制台的输出是正确的并且保持不变,直到当前的JVM实例在那里存在

3) 仅创建一个JFrame并将此容器重新用于另一个用户操作

  • JFrame#getContentPane.removeAll()

  • JFrame.add(whatever)

  • (Java7)JFrame#revalidate();(Java6 更好用,JPanel或者容器ContentPane也可以这样做)

  • JFrame#repaint();

编辑

您可以测试 DefaultCloseOperations 和 JFrame#dispose() 的其余设置

您在此处发布的代码与此代码中的 JMenuItem 相同

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

public class ClosingFrame extends JFrame {

    private JMenuBar MenuBar = new JMenuBar();
    private JFrame frame = new JFrame();
    private static final long serialVersionUID = 1L;
    private JMenu File = new JMenu("File");
    private JMenuItem Exit = new JMenuItem("Exit");
    private JFrame frame1 = new JFrame();

    public ClosingFrame() {
        File.add(Exit);
        MenuBar.add(File);
        Exit.setBorder(new EmptyBorder(10, 10, 10, 10));
        Exit.addActionListener(new ExitListener());
        WindowListener exitListener = new WindowAdapter() {

            @Override
            public void windowClosing(WindowEvent e) {
                int confirm = JOptionPane.showOptionDialog(frame,
                        "Are You Sure to Close this Application?",
                        "Exit Confirmation", JOptionPane.YES_NO_OPTION,
                        JOptionPane.QUESTION_MESSAGE, null, null, null);
                if (confirm == 0) {
                    System.exit(1);
                }
            }
        };
        frame.addWindowListener(exitListener);
        frame.setDefaultCloseOperation(EXIT_ON_CLOSE);
        frame.setJMenuBar(MenuBar);
        frame.setPreferredSize(new Dimension(400, 300));
        frame.setLocation(100, 100);
        frame.pack();
        frame.setVisible(true);

        frame1.addWindowListener(exitListener);
        frame1.setDefaultCloseOperation(EXIT_ON_CLOSE);
        frame1.setPreferredSize(new Dimension(400, 300));
        frame1.setLocation(500, 100);
        frame1.pack();
        frame1.setVisible(true);
    }

    private class ExitListener implements ActionListener {

        @Override
        public void actionPerformed(ActionEvent e) {
            int confirm = JOptionPane.showOptionDialog(frame,
                    "Are You Sure to Close this Application?",
                    "Exit Confirmation", JOptionPane.YES_NO_OPTION,
                    JOptionPane.QUESTION_MESSAGE, null, null, null);
            /*JOptionPane.showMessageDialog(null, "Whatever", "Whatever",
                    JOptionPane.ERROR_MESSAGE);
            int confirm1 = JOptionPane.showOptionDialog(frame1,
                    "Are You Sure to Close this Application?",
                    "Exit Confirmation", JOptionPane.YES_NO_OPTION,
                    JOptionPane.QUESTION_MESSAGE, null, null, null);*/
            if (confirm == 0) {
                frame.dispose();
            }
        }
    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(new Runnable() {

            @Override
            public void run() {
                ClosingFrame cf = new ClosingFrame();
            }
        });
    }
}

编辑 2

在当前 API 的实现中没有任何区别

JFrame#dispose();

JFrame#setVisible(false);

也不影响UsedMemoryfrom current JVM instance,这个/这些容器会留在内存中,直到当前的 JVM 实例存在

于 2012-05-02T22:03:16.170 回答
1

只要有非守护线程,VM 就会继续运行。您可以使用显式退出 VM System.exit(status)。查看正在运行的线程的最简单方法可能是使用 JConsole 附加到进程。主线程将继续运行,直到您从main主类中的方法返回。

于 2012-05-02T21:37:21.920 回答