我的框架为什么不配置?

时间:2012-05-02 21:08:26

标签: java swing

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

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

我可以看到日志消息但是VM仍在运行。我想也终止它。我做错了什么?

似乎还在运行一个非deamon线程,但我不明白为什么:

enter image description here

3 个答案:

答案 0 :(得分: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(真);了Thread.sleep(8000); SwingUtilities.invokeLater(new Runnable(){public void run(){// TODO Auto-generated method stub 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();
  }
}

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

答案 1 :(得分: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);

也不是来自当前UsedMemory的{​​{1}}的inpact,这个/这些容器会保留in the memory untill current JVM instance exists

答案 2 :(得分:1)

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