-2

問題の解決策をテストしていました

この場合、JVM またはリフレクションの新しいインスタンスが役立ちますか

私が遭遇したのは、不動産ゲームなどのアプリケーションを呼び出そうとすると、このソリューションが機能しないということでした。そのため、 main を呼び出した後に次のコードを追加する代わりに、 Applic2

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


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

                  aFrame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);

              }
            }

以下に示すように、アクション JFrame.EXIT_ON_CLOSE を JFrame.DISPOSE_ON_CLOSE に変更し続ける非同期スレッドを作成しました。

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);
                }
            }
        }
    }
}

MyApp クラスの start メソッドでこのスレッド インスタンスを呼び出します。しかし、解決策は機能していません。それでも、1つのフレームを閉じるとすべてのフレームが閉じるという同じ問題に直面しています。なぜそれが提案され、これを克服する方法が起こっているのですか??

次の問題を解いてください:

問題をより詳細に提示しましょう

Real Estate ゲームコードをワークスペースに追加する

次のパッケージを RealEstate コードに追加します。

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());

                }

            }

        }


    }

}

次に、MyApplication パッケージのメインを呼び出します。これにより、RealEstate ゲームが呼び出されます。これは解決策が機能しない場所です。別の RealEstate フレームを閉じてみて、アプリケーション全体が閉じることを確認してください。

4

3 に答える 3

5

Real Estate ゲームのコードをすばやく確認したところ、MainWindow.java次の場所に問題が見つかりました。

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

それでもウィンドウを閉じたい場合は、外部からこれについて何ができるかわかりません。

于 2012-07-23T12:22:05.037 に答える
2

それで、簡単なテストを行ったところ、これをうまく機能させることができました。

まず、3 つの JFrames を作成しました (急いでいたため、すべて同じ原因です)。デフォルトの close 値は に設定されていEXIT_ON_CLOSEます。

1 つを閉じると、3 つすべてが閉じられることを確認しました。

次に、使用javax.swing.Timer可能なフレームのリストを繰り返し循環させ、デフォルトの近い値を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());

            }

        }

    }

}

実行すると、次の出力を監視できました

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

ご覧のとおり。最初の繰り返しで、フレームは「3」から「2」に変わり、出力にうんざりしてプログラムを強制終了するまでそのままです。

また、1 つ以上のフレームを閉じてもプログラムが終了しないことも確認しました。

さて、重要な注意事項を 1 つ。これは、実現された (画面に表示された) フレームに対してのみ機能すると思いますが、これをテストして、何が得られるかを確認できます;)

于 2012-07-23T10:59:44.757 に答える
1

1 つの方法 (必ずしも最善とは限りません) は、カスタム セキュリティ マネージャーを実装することです。

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;
  }
}
于 2012-07-24T00:03:27.157 に答える