5

I'm currently working on an application for work that has a main JFrame that always exists. I currently have a child JDialog that shows up on a button press. This frame has a JMenu with an item to "log out of the display." I've been tasked to ensure this child JDialog goes away when the log out of the display option is pressed. When the logout occurs, the main display is set invisible via:

mainFrame.setVisible(false);

The child JDialog has the default close operation:

DISPONSE_ON_CLOSE

When the user logs back in, the first thing that's done is:

mainFrame.setVisible(true); 

When this happens, the child dialog shows back up. Looking at the JDialog Javadoc, this seems to be expected behavior. However I haven't found a way to break the parent/child releationship or completely destroy the child JDialog. It also seems like the JDialog will remain until it has been GC, which may not happen in a timely manner.

Here is a sample program that simulates the behavior I'm seeing:

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.ComponentAdapter;
import java.awt.event.ComponentEvent;

import javax.swing.JDialog;
import javax.swing.JFrame;
import javax.swing.JToggleButton;
import javax.swing.SwingUtilities;

public class WindowTest { 

    public static void createAndShowGUI() {
        JFrame aFrame = new JFrame("LAUNCHER");
        final JFrame aParent = new JFrame("PARENT"); 
        final JDialog aChild = new JDialog(aParent);

        aParent.setSize(200,200);

        final JToggleButton showParentButton = new JToggleButton("HIDE");

        showParentButton.addActionListener(new ActionListener() { 
            public void actionPerformed(ActionEvent e) {
                showParentButton.setText(!showParentButton.isSelected() ? "SHOW": "HIDE");
                aParent.setVisible(!showParentButton.isSelected());
            }
        });

        aChild.setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE); 
        aChild.setSize(200,200);
        aParent.addComponentListener(new ComponentAdapter() {

            public void componentHidden(ComponentEvent e) {
                aChild.dispose(); 
                aChild.setVisible(false);
            }
        });
        aFrame.setContentPane(showParentButton);
        aFrame.pack();
        aFrame.setVisible(true);
        aParent.setVisible(true);
        aChild.setVisible(true);
    }
    public static void main(String [] args) {
        SwingUtilities.invokeLater(new Runnable(){
            public void run() {
                createAndShowGUI();
            }
        });
     }
 }

When the parent is hidden, the child is disposed. When the parent is shown, the child shows back up. What's really weird is that when I press the X on the child: when the parent is hidden and then shown again, the child does not show back up.

The only difference I see is that clicking the X also fires a WindowClosing event. I tried the dispatch the even, in the componentHidden method above by:

//Added into the constructor
//add to the imports: import java.awt.event.WindowEvent;
aParent.addComponentListener(new ComponentAdapter() {

        public void componentHidden(ComponentEvent e) {
            aChild.dispose(); 
            aChild.setVisible(false); 
            WindowEvent closingEvent = 
                new WindowEvent(aChild, WindowEvent.WINDOW_CLOSING); 
            aChild.dispatchEvent(closingEvent);
        }
    });

And that didn't solve the problem.

Currently it looks like my only option is to change the type of child to a JFrame. I just wanted to know if there was a proper way of disposing a child JDialog.

I'm currently running with Java version: 1.7.0_76 64 bit on Redhat Enterprise Linux Server release 6.4.

lordoku
  • 908
  • 8
  • 22
  • by default isn't possible - [dispose == setVisible(false)](http://stackoverflow.com/questions/6309407/remove-top-level-container-on-runtime), reuse JDialog for anther action, use HIDE_ON_CLOSE – mKorbel Sep 18 '15 at 16:46
  • I can't reuse the dialog. (Requirements, poor design, existing code, etc) – lordoku Sep 18 '15 at 16:57
  • @mKorbel The answers to that question seem to indicate that a Dialog is in fact eligible for garbage collection, once it is disposed. As always, there is no guarantee that an object with no references to it will be garbage-collected immediately. – VGR Sep 18 '15 at 17:11
  • So basically this is impossible. Seems weird that you can't remove a child from a parent frame. – lordoku Sep 18 '15 at 17:26
  • I've never used JFX but Swing... Have you tried removing all the childs and then adding them again w/o the JDialog when the user want to login? – Yassin Hajaj Sep 18 '15 at 18:43
  • 1
    `Here is a sample program that simulates the behavior I'm seeing:`- 1) variable names should NOT start with an upper case character. 2) the code should be complete so we can copy/paste/compile. It doesn't compile so I can't test it. – camickr Sep 18 '15 at 18:45
  • @VGR 1. Top-Level Container is based on peers from Native OS, 2. missing finalize() in API for GC, 3. then exist (incl. JOptionPane), are accesible until current JVM exist, 4. :-) – mKorbel Sep 18 '15 at 19:56
  • For comparison dispose vs setVisible(false) see http://stackoverflow.com/questions/7256606/jdialog-setvisiblefalse-vs-dispose – keuleJ Sep 19 '15 at 19:57
  • @YassinHH there doesn't seem to be any way to remove the child. Do you know if there's a specific method. Also we're running with a JDK 1.7, so JavaFx is out of the question. – lordoku Sep 21 '15 at 13:00
  • `there doesn't seem to be any way to remove the child` - works for me, but your posted code doesn't compile so I can't see what your code is doing. – camickr Sep 21 '15 at 14:55

1 Answers1

4

I wasn't aware the naming conventions affected the compile.

It doesn't. Conventions are done for consistency and readability and maintainability. The person who writes the code is not always the person that maintains the code. So if you want other people to read your code, especially when asking for help, follow the standards.

You can start with Java Programming Style Guidelines

I'm copying the code by hand from another screen per my companies standards.

This is a complete waste of time. There is nothing proprietary about your code. Again when you ask a question, the code should be in the form of a SSCCE so it demonstrates the problem. This allows you to remove all the unnecessary code.

it would be straight forward to figure out the imports.

Exactly, so you should do it. You want us to help you, so why should we spend the time figuring it out??? Make is as easy as possible for people to want to help you.

Adding the imports did not help. The code you posted still does not compile so I don't know if it accurately reflects the problem you are attempting to describe.

Again the point of posting code is so that we can copy/paste/compile/test. Until you post a proper SSCCE I will not provide the answer.

Edit:

From my testing, if the visibility of the child window is changed by the visibility of the parent when the parent is made non-visible, then the visibility of the child is also changed by the parent when it is made visible. So it looks like the parent is retaining the state of the child windows when the visibility changes.

So the solution is to make the child window non-visible before the parent:

showParentButton.setText(!showParentButton.isSelected() ? "SHOW": "HIDE");
aChild.setVisible(false); // add this
aParent.setVisible(!showParentButton.isSelected());

If you don't have a reference to the child window then I guess you can use the Windows.getOwnedWindows() method to access all the child windows.

Another edit:

As a hack I created a custom dialog that can't be shown again once it is disposed:

    final JDialog aChild = new JDialog(aParent)
    {
        private boolean disposed = false;

        @Override
        public void dispose()
        {
            super.dispose();
            disposed = true;
        }

        @Override
        public void show()
        {
            if (disposed)
                return;

            super.show();
        }
    };
camickr
  • 321,443
  • 19
  • 166
  • 288
  • I went ahead and updated the sample and verified that it compiles. If there are any other issues, please let me know. I'm sorry I didn't follow proper standards; initially I copied it down as pseudo code because I was transposing it by hand and I felt the imports would not benefit anybody. I'm sorry if I came across harsh, I really felt this was a nitpick and not a helpful suggestion. Now that I understand that others pull down the code, I'll strive to make sure my questions are more complete. – lordoku Sep 21 '15 at 15:06
  • 1
    Down voting, because this doesn't answer the question, although it is a good reminder of how to ask a question. – lordoku Sep 21 '15 at 15:10
  • Wow, you are making it really difficult to help. I would have posted it as a comment, but there was way too much to say in a single comment. It answers questions about how to ask a question and how to follow standards which will be beneficial in the future. Anyway, I've updated the answer with my findings. – camickr Sep 21 '15 at 15:30
  • Sorry I'm trying not to be difficult, and failing. I was overreacting because I felt like I wasn't getting helped. I took a deep breath and understood that you were just trying to help. I'm sorry I read that as a harsh criticism, but it really was just matter of fact. Once again I'm sorry and I'll update your answer. – lordoku Sep 21 '15 at 15:34
  • I tried setting the child's setVisible to false, like your answer and the child still shows up. I'll update my question to include my environment. – lordoku Sep 21 '15 at 15:39
  • So it looks like this answer works in Windows but not on Redhat. Both tests were running the same JRE version. Also the program here is a simulation of our real product. On the real product we were relying on the componentHidden event of the parent to close the child, to handle all cases where the parent is hidden. – lordoku Sep 21 '15 at 15:46
  • @lordoku, I also tested on Windows, where it worked. So I guess I can't offer any more suggestions. – camickr Sep 21 '15 at 16:59
  • Thanks again for your help. Once again, I'm sorry for being difficult. I'll work on managing my frustrations. – lordoku Sep 21 '15 at 18:16
  • @lordoku, another possible hack (that works on Windows). – camickr Sep 21 '15 at 18:59