Unfortunately, it looks like this recently closed question was not well understood. Here is the typical output:
run:
Trying to Remove JDialog
Remove
I have completely reworked your example:
setLocation()
, unused constructor...)javax.swing.Timer
instead of a Thread
for disposing of the dialogThread
for forcing GC (not a good idea in the EDT)Window.getWindows()
is 2 (not 1), because in Swing, if you open a dialog with no parent, then a special invisible frame will be created to use it as parent (for all ownerless dialogs actually), once created, that frame cannot be removed.The resulting snippet follows:
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.*;
public class RemoveDialogOnRuntime extends JFrame {
private static final long serialVersionUID = 1L;
private boolean runProcess;
private int maxLoop = 0;
private Timer timer;
public RemoveDialogOnRuntime() {
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setPreferredSize(new Dimension(300, 300));
setTitle("Remove Dialog On Runtime");
setLocation(150, 150);
pack();
setVisible(true);
addNewDialog();
}
private void addNewDialog() {
DialogRemove firstDialog = new DialogRemove();
remWins();
}
private void remWins() {
runProcess = true;
timer = new Timer(1000, new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
if (runProcess) {
for (Window win: Window.getWindows()) {
if (win instanceof JDialog) {
System.out.println(" Trying to Remove JDialog");
win.dispose();
}
}
System.out.println(" Remove Cycle Done :-)");
runProcess = false;
new Thread() {
@Override
public void run() {
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
Runtime.getRuntime().gc();
}
}.start();
} else {
pastRemWins();
runProcess = true;
}
}
});
timer.setRepeats(true);
timer.start();
}
private void pastRemWins() {
System.out.println(" Checking if still exists any of TopLayoutContainers");
Window[] wins = Window.getWindows();
for (int i = 0; i < wins.length; i++) {
if (wins[i] instanceof JFrame) {
System.out.println("JFrame");
} else if (wins[i] instanceof JDialog) {
System.out.println("JDialog");
} else {
System.out.println(wins[i].getClass().getSimpleName());
}
}
// We must expect 2 windows here: this (RemoveDialogOnRuntime) and the parent of all parentless dialogs
if (wins.length > 2) {
wins = null;
maxLoop++;
if (maxLoop <= 3) {
System.out.println(" Will Try Remove Dialog again, CycleNo. " + maxLoop);
System.out.println(" -----------------------------------------------------------");
remWins();
} else {
System.out.println(" -----------------------------------------------------------");
System.out.println("*** End of Cycle Without Success, Exit App ***");
closeMe();
}
} else {
timer.stop();
}
}
private void closeMe() {
System.exit(0);
}
private class DialogRemove extends JDialog {
private static final long serialVersionUID = 1L;
private DialogRemove() {
setTitle("SecondDialog");
setPreferredSize(new Dimension(200, 200));
setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE);
setModalityType(Dialog.ModalityType.MODELESS);
pack();
setVisible(true);
}
}
public static void main(String args[]) {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
RemoveDialogOnRuntime superConstructor = new RemoveDialogOnRuntime();
}
});
}
}
The important conclusions are:
Window.getWindows()
(that one looks like a bug to me but I think the reason is that Swing keeps a WeakReference
to all windows, and this WeakReference
is not released until a GC has occurred.Hope this gives a clear and complete answer to your problem.