Reputation:
I'm using the following method to display a frame:
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();
}
Then i do some calculation and after that, I want to dispose the frame again:
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();
}
I can see the log messages but however, the VM is still running. I want to also terminate it. What am I doing wrong?
There seems to still be running one non deamon thread, but I can't see why:
Upvotes: 1
Views: 1109
Reputation: 109823
if you'll to call
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();
}
then code will be executed but
1) only if is done on EDT, otherwise ... outside EDT Top-Level Containers
are sticked on the screen
or
2) Top-Level Containers
missed method finalize()
, then never will be GC'ed
(some restriction based on resources from Windows NT/2000
that alive ...), then output from console is correct and stay remaind unchanged until current JVM instance exist there
3) create only one JFrame
and re_use this container for another user action by
JFrame#getContentPane.removeAll()
JFrame.add(whatever)
(Java7) JFrame#revalidate();
(for Java6 is better to use JPanel
or container from ContentPane
can do that too)
JFrame#repaint();
EDIT
rest of how set for DefaultCloseOperations and JFrame#dispose() you can test
in code that you posted here is the same as from JMenuItem in this code
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();
}
});
}
}
EDIT 2
in the current API's implementations isn't any difference betweens
JFrame#dispose();
and
JFrame#setVisible(false);
nor with inpact to the UsedMemory
from current JVM instance
, this/these containers stays in the memory untill current JVM instance exists
Upvotes: 2
Reputation: 285460
You're not setting the JFrame's default close operation and it's defaulting to JFrame.HIDE_ON_CLOSE
.
Add to your JFrame set up code:
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
If your JFrame is your application and you want to exit everything when the JFrame closes, or
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
if your JFrame is not the whole application and you want to stop the Swing thread but continue processing.
For more on this, please check out the JFrame API
Edit:
Regarding your comment,
@HovercraftFullOfEels okay if what you say is right why is my frame disappearing in this code: 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() { // TODO Auto-generated method stub jf.dispose(); } }); }
Which I translate to:
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();
}
});
}
This only exits if there are no more non-daemon threads left. If you give it a non-daemon thread, this will keep running. For e.g.,
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();
}
}
Your code will keep running in this example.
Upvotes: 2
Reputation: 36071
The VM will continue running as long as there are non-daemon threads. You can explicitly exit the VM using System.exit(status)
. The easiest way to see what threads are running is probably to use JConsole to attach to the process. The main thread will continue running until you have returned from the main
method in the main class.
Upvotes: 1