-
Enhancement
-
Resolution: Not an Issue
-
P4
-
None
-
1.3.0
-
generic, x86
-
generic, windows_2000
Name: krC82822 Date: 11/08/2000
orig synopsis: "Multiple WINDOW_CLOSED events fired for Dialog"
8 Nov 2000, eval1127@eng -- verified problem and workaround under 1.3.0.
----------------
java version "1.3.0"
Java(TM) 2 Runtime Environment, Standard Edition (build 1.3.0-C)
Java HotSpot(TM) Client VM (build 1.3.0-C, mixed mode)
Basically the problem is that when a dialog (non-modal in this case) is
disposed, the reference to it is not removed from its parent. Looking through
the source for Window.java, there is a method called removeOwnedWindow. In the
finalize method of Window, there is this code:
<pre>
if (parent != null) {
((Window)parent).removeOwnedWindow(weakThis);
}
</pre>
This code removes the reference to this from its parent. The problem is that
this should probably also be done in dispose. It is stated in the
documentation that finalize is NOT guaranteed to be called, and even if it is
you have no idea when it would get called. This can cause multiple window
events to be fired as is shown in my test example:
*********** Source *************
<pre>
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class Test extends JFrame implements ActionListener
{
public static void main(String [] args)
{
JFrame f = new JFrame("Kill window");
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JLabel l = new JLabel("<html>This window is just used to keep the JVM
running<br>and to give a way to kill the process</html>");
f.getContentPane().add(l);
f.pack();
f.setVisible(true);
Test t = new Test();
t.setVisible(true);
}
public Test()
{
super("Test window");
setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
JPanel p = new JPanel();
JButton b = new JButton("Open Dialog");
b.addActionListener(this);
p.add(b);
b = new JButton("Close Dialog");
b.addActionListener(this);
p.add(b);
setContentPane(p);
pack();
}
public void actionPerformed(ActionEvent e)
{
String cmd = e.getActionCommand();
if(cmd.equals("Open Dialog"))
{
d = new JDialog(this, "dialog", false);
d.setDefaultCloseOperation(JDialog.DO_NOTHING_ON_CLOSE);
d.addWindowListener(new WindowAdapter(){
public void windowClosed(WindowEvent e)
{
System.out.println("got window closed event from dialog");
}
});
d.getContentPane().add(new JLabel("dialog"));
d.pack();
d.show();
}else if(cmd.equals("Close Dialog"))
{
d.setVisible(false);
d.dispose();
}
}
private JDialog d;
}
</pre>
******** End of source ************
If you run the above example you will get two frames. One of them is just to
keep the JVM running and to give an easy way to close the program when you are
finished, and the label added to it will tell you that. The other frame will
have two buttons: "Open Dialog" and "Close Dialog". If you press the "Open
Dialog" button, a dialog will appear. If you then press the "Close Dialog"
button the dialog will go away and you will get a printed message of "got
window close event from dialog". At this point dispose has been called on the
dialog signifying that it will never be set visible again. Then if you hit the
button to close the frame with the buttons(x on windows look and feel), you
will see that you get the "got window close event from dialog" message again.
This means that the window closing event was fired a second time after the
dialog may have been closed for some time.
(Review ID: 110536)
======================================================================
Name: yyT116575 Date: 11/28/2000
java version "1.3.0"
Java(TM) 2 Runtime Environment, Standard Edition (build 1.3.0)
Java HotSpot(TM) Client VM (build 1.3.0, mixed mode)
Since Java 1.2 the AWT Dialog has had a number of problems evident when run
on Linux and to some extent even on Sparc platforms.
When a Dialog is requested to be displayed for the second time, it does
not always appear on the screen. If it is a modal dialog, the whole
program is then locked up in an unusable state.
JDK 1.3 does not fix the problem. It does not appear on the Windows
version of Java. The problem is evident even in the example program
that Sun provided on the use of Dialogs (DialogWindow.java below). This
works fine when run in Netscape (JDK 1.1).
I have played with the code and have learned a little about how to avoid
the problem. Of the many ways of removing a Dialog from the screen when
it is no longer wanted (eg. hide(), setVisible(false), dispose(),
removeNotify() ), the first two cause problems. However, I have found
that if dispose() is used then the second display of the Dialog is always
successful.
I am using fvwm2 window manager on either my Linux pc running Red Hat 6.2
or on our Sparc SUNW,Ultra-Enterprise running Solaris 5.7 and accessed
via a Tektronix X-terminal.
-------------------------------------------------------------------------
import java.awt.*;
import java.awt.event.*;
public class DialogWindow extends Frame
implements ActionListener {
boolean inAnApplet = true; //should be private
private SimpleDialog dialog;
private TextArea textArea;
String newline;
public DialogWindow() {
textArea = new TextArea(5, 40);
textArea.setEditable(false);
add("Center", textArea);
Button button = new Button("Click to bring up dialog");
button.addActionListener(this);
Panel panel = new Panel();
panel.add(button);
add("South", panel);
addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e) {
if (inAnApplet) {
setVisible(false);
dispose();
} else {
System.exit(0);
}
}
});
newline = System.getProperty("line.separator");
}
public void actionPerformed(ActionEvent event) {
if (dialog == null) {
dialog = new SimpleDialog(this, "A Simple Dialog");
}
dialog.setVisible(true);
}
public void setText(String text) {
textArea.append(text + newline);
}
public static void main(String args[]) {
DialogWindow window = new DialogWindow();
window.inAnApplet = false;
window.setTitle("DialogWindow Application");
window.pack();
window.setVisible(true);
}
}
class SimpleDialog extends Dialog implements ActionListener {
TextField field;
DialogWindow parent;
Button setButton;
SimpleDialog(Frame dw, String title) {
super(dw, title, false);
parent = (DialogWindow)dw;
//Create middle section.
Panel p1 = new Panel();
Label label = new Label("Enter random text here:");
p1.add(label);
field = new TextField(40);
field.addActionListener(this);
p1.add(field);
add("Center", p1);
//Create bottom row.
Panel p2 = new Panel();
p2.setLayout(new FlowLayout(FlowLayout.RIGHT));
Button b = new Button("Cancel");
b.addActionListener(this);
setButton = new Button("Set");
setButton.addActionListener(this);
p2.add(b);
p2.add(setButton);
add("South", p2);
//Initialize this dialog to its preferred size.
pack();
}
public void actionPerformed(ActionEvent event) {
Object source = event.getSource();
if ( (source == setButton)
| (source == field)) {
parent.setText(field.getText());
}
field.selectAll();
setVisible(false);
//dispose();
}
}
// If the dispose() is uncommented (to replace the preceding setVisible),
// the Dialog is successfully displayed on the second and subsequent
// attempts as well as the first one.
(Review ID: 112717)
======================================================================
- relates to
-
JDK-4755510 Hang with dialogs remote displayed from solaris to linux
-
- Closed
-