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

ログ メッセージは表示されますが、VM はまだ実行中です。私も解約したいです。私は何を間違っていますか?

まだデーモン以外のスレッドが 1 つ実行されているようですが、その理由はわかりません。

ここに画像の説明を入力

4

3 に答える 3

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) コンテナを 1 つだけ作成し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 インスタンスが存在するまでJVM instance、この/これらのコンテナーはメモリ内に留まります。

于 2012-05-02T22:03:16.170 に答える
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 自動生成メソッド スタブ 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 に答える
1

非デーモン スレッドがある限り、VM は実行を続けます。を使用して VM を明示的に終了できますSystem.exit(status)。どのスレッドが実行されているかを確認する最も簡単な方法は、おそらく JConsole を使用してプロセスに接続することです。mainメイン クラスのメソッドから戻るまで、メイン スレッドは実行を続けます。

于 2012-05-02T21:37:21.920 に答える