-2

I was testing the solution for the problem

Will new instance of JVM or reflection help in this case

What I encountered was that this solution does not work if I try to invoke an application such as Real Estate game . So in place of just adding the following code after invoking main of Applic2

        Frame[] f2 = JFrame.getFrames();
        for(Frame fx: f2){


              if (fx instanceof JFrame) {
                  JFrame aFrame = (JFrame)fx;

                  aFrame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);

              }
            }

I created a asynchronous thread that keeps on changing the action JFrame.EXIT_ON_CLOSE to JFrame.DISPOSE_ON_CLOSE as shown below

import java.awt.Frame;

import javax.swing.JFrame;

public class FrameMonitor extends Thread{

    @Override
    public void run(){

        while(true){
            Frame[] f2 = JFrame.getFrames();

            for(Frame fx : f2){

                if(fx instanceof JFrame){
                    JFrame aframe =(JFrame)fx;
                    aframe.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
                }
            }
        }
    }
}

and invoking this this thread instance by its start method in MyApp class. but the solution is not working. Still I am facing the same problem of all frame closing on closing one frame. Why is it happening any suggestions and how to overcome this??

Please go through the following problem :

Let me present the problem in more detail

Add the Real Estate game code to workspace

Add the following package to the RealEstate code

package MyApplication;

import java.awt.Frame;
import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

import javax.swing.JFrame;

import edu.ncsu.realestate.gui.Main;

public class MYApp {

    @SuppressWarnings({ "unchecked", "rawtypes" })
    public static void main(String arg[]){

        FrameMonitor monitor = new FrameMonitor();
        JFrame f = new JFrame();
        f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        f.setSize(200,200);
        f.setVisible(true);
        Class cls = Main.class;
        Object[] actuals = { new String[] {} };
    //  cls.
        Method[] mts=cls.getMethods();
        for(Method m : mts){
            //System.out.println(m);
        }
        Method m = null;
        try {
            m=cls.getMethod("main", new Class[] { String[].class } );
        } catch (NoSuchMethodException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (SecurityException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
            try {
                m.invoke(null,actuals);
            } catch (IllegalAccessException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            } catch (IllegalArgumentException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            } catch (InvocationTargetException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }

            Frame[] f2 = JFrame.getFrames();
            for(Frame fx: f2){
                System.out.println(fx.getTitle());
                //  fx.setVisible(false);

                  if (fx instanceof JFrame) {
                     // System.out.println("M here");
                    //  System.out.println(fx.getTitle());
                      System.out.println(fx.getName());
                      JFrame aFrame = (JFrame)fx;

                      aFrame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);

                  }
                }

    }


}



package MyApplication;

import java.awt.Frame;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.JFrame;
import javax.swing.Timer;

public class FrameMonitor{

    public FrameMonitor(){
    Timer timer = new Timer(10000, new FrameMonitor2());
    timer.setCoalesce(true);
    timer.setRepeats(true);
    timer.start();

}


    public static class FrameMonitor2 implements ActionListener {

        @Override
        public void actionPerformed(ActionEvent ae) {

            Frame[] frames = Frame.getFrames();
            for (Frame frame : frames) {

                if (frame instanceof JFrame) {

                    JFrame change = (JFrame) frame;
                    System.out.println("Before = " + change.getTitle() + " = " + change.getDefaultCloseOperation());
                    ((JFrame)frame).setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
                    System.out.println("After = " + change.getTitle() + " = " + change.getDefaultCloseOperation());

                }

            }

        }


    }

}

Now invoke the main of MyApplication package and which inturn invokes RealEstate game. This is where the solution does not work, try closing different RealEstate frames and see the entire application closes.

Community
  • 1
  • 1
Sanyam Goel
  • 2,138
  • 22
  • 40
  • 1
    Quick note, don't modify Swing components from any thread other than the ETD, while we're pondering your issue, have a read of Concurrency in Swing http://docs.oracle.com/javase/tutorial/uiswing/concurrency/index.html – MadProgrammer Jul 23 '12 at 10:27

3 Answers3

5

I checked the code for the Real Estate game real quick and found your problem in MainWindow.java:

this.addWindowListener(new WindowAdapter(){
    public void windowClosing(WindowEvent e) {
        System.exit(0);
    }
});

I'm not sure what, if anything, you can do about this from the outside if you still want the window to close.

Jacob Raihle
  • 3,720
  • 18
  • 34
  • 1
    +1 for hunting it down :-) As to what to do with it: if there's a reference to that window, remove the listener (by looping through window.getWindowListener() and remove the anonymous in the same name context, something like MainWindow$ – kleopatra Jul 23 '12 at 13:49
2

So, I've done a quick test and I can get this to work fine.

First, I created three JFrames (all identical cause I was in a hurry), with there default close values set to EXIT_ON_CLOSE.

I verified that if I closed one, it would close all three.

I then used a javax.swing.Timer to repeatedly cycle through the list of available frames and set there default close values to DISPOSE_ON_CLOSE

Timer timer = new Timer(1000, new UpdateTask());
timer.setCoalesce(true);
timer.setRepeats(true);
timer.start();

...

public static class UpdateTask implements ActionListener {

    @Override
    public void actionPerformed(ActionEvent ae) {

        Frame[] frames = Frame.getFrames();
        for (Frame frame : frames) {

            if (frame instanceof JFrame) {

                JFrame change = (JFrame) frame;
                System.out.println("Before = " + change.getTitle() + " = " + change.getDefaultCloseOperation());
                ((JFrame)frame).setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
                System.out.println("After = " + change.getTitle() + " = " + change.getDefaultCloseOperation());

            }

        }

    }

}

Once executed I was able to monitor the following output

Before = Frame 01 = 3
After = Frame 01 = 2
Before = Frame 02 = 3
After = Frame 02 = 2
Before = Frame 03 = 3
After = Frame 03 = 2
Before = Frame 01 = 2
After = Frame 01 = 2
Before = Frame 02 = 2
After = Frame 02 = 2
Before = Frame 03 = 2
After = Frame 03 = 2

As you see. On the first iteration, the frames change from "3" to "2" and remains that way till I get sick of the output and kill the program.

I also checked that close one or more of the frames would NOT exit the program.

Now, one important note. I believe this is only going to work for frames that have been realised (made visible on the screen), but you can test this and see what you get ;)

MadProgrammer
  • 343,457
  • 22
  • 230
  • 366
  • This solution is not working for Real-estate problem :( as mentioned in the link before why is it happening is it that the frame object of RealEstate game is not acessible or locked?? – Sanyam Goel Jul 23 '12 at 11:14
1

One way (not necessarily the best) is to implement a custom security manager.

import java.awt.*;
import java.awt.event.*;
import java.security.Permission;

/** NoExit demonstrates how to prevent 'child'
applications from ending the VM with a call
to System.exit(0).
@author Andrew Thompson */
public class NoExit extends Frame implements ActionListener {

  Button frameLaunch = new Button("Frame"),
     exitLaunch = new Button("Exit");

  /** Stores a reference to the original security manager. */
  ExitManager sm;

  public NoExit() {
     super("Launcher Application");

     sm = new ExitManager( System.getSecurityManager() );
     System.setSecurityManager(sm);

     setLayout(new GridLayout(0,1));

     frameLaunch.addActionListener(this);
     exitLaunch.addActionListener(this);

     add( frameLaunch );
     add( exitLaunch );

     pack();
     setSize( getPreferredSize() );
  }

  public void actionPerformed(ActionEvent ae) {
     if ( ae.getSource()==frameLaunch ) {
        TargetFrame tf = new TargetFrame();
     } else {
        // change back to the standard SM that allows exit.
        System.setSecurityManager(
           sm.getOriginalSecurityManager() );
        // exit the VM when *we* want
        System.exit(0);
     }
  }

  public static void main(String[] args) {
     NoExit ne = new NoExit();
     ne.setVisible(true);
  }
}

/** This example frame attempts to System.exit(0)
on closing, we must prevent it from doing so. */
class TargetFrame extends Frame {
  static int x=0, y=0;

  TargetFrame() {
     super("Close Me!");
     add(new Label("Hi!"));

     addWindowListener( new WindowAdapter() {
        public void windowClosing(WindowEvent we) {
           System.out.println("Bye!");
           System.exit(0);
        }
     });

     pack();
     setSize( getPreferredSize() );
     setLocation(++x*10,++y*10);
     setVisible(true);
  }
}

/** Our custom ExitManager does not allow the VM
to exit, but does allow itself to be replaced by
the original security manager.
@author Andrew Thompson */
class ExitManager extends SecurityManager {

  SecurityManager original;

  ExitManager(SecurityManager original) {
     this.original = original;
  }

  /** Deny permission to exit the VM. */
   public void checkExit(int status) {
     throw( new SecurityException() );
  }

  /** Allow this security manager to be replaced,
  if fact, allow pretty much everything. */
  public void checkPermission(Permission perm) {
  }

  public SecurityManager getOriginalSecurityManager() {
     return original;
  }
}
Andrew Thompson
  • 168,117
  • 40
  • 217
  • 433