-1

Java ドキュメントには次のように書かれています。

アプレットでは、invokeAndWait() を使用して init() メソッドから GUI 作成タスクを起動する必要があります。そうしないと、GUI が作成される前に init() が返され、Web ブラウザがアプレットを起動する際に問題が発生する可能性があります。

init()GUI が作成される前に戻ったら何が問題なのですか? ブラウザにどのような問題が発生する可能性がありますか?

ドキュメントはさらに次のように述べています。

他の種類のプログラムでは、通常、GUI 作成タスクのスケジューリングは最初のスレッドが最後に行うことなので、invokeLater() を使用するか、invokeAndWait() を使用するかは問題ではありません。

GUI 作成タスクが最後に行われると、どのように変化しますか? また、GUI の作成が最初のスレッドによって実行される最後のタスクでない場合、通常のinvokeAndWait()方法についても述べていinvokeLater()ます。

彼らが言おうとしていることは理解していると思いますが、それでも確認したいので、質問を投稿します。事前にサンクス!!

4

4 に答える 4

4

init()GUI が作成される前に戻ったら何が問題なのですか? ブラウザにどのような問題が発生する可能性がありますか?

私の主な懸念はstart()、コンポーネントの作成が完了する前にメソッドが呼び出されることです。コンポーネントが開始メソッドで参照されている場合、NullPointerException.

..スタンドアロン プログラムでも同じことが起こりませんか?

デスクトップ アプリケーションにはメソッドがありませんstart()。メソッドはアプレットのライフサイクルの一部ですが、アプリケーションのライフサイクルではありません。

于 2013-03-10T06:55:25.870 に答える
0

例を使って私の経験をお話しします-2つのコンストラクター(1つはsuper()を呼び出し、もう1つはthis()を呼び出し、その引数からFrameをセットアップします)を備えたJMenuBarを備えたアプレット(拡張JApplet)があるとします。クラスにはmainメソッド(アプレットには不要)もあります。

  1. JFrameをインスタンス化します
  2. このFrameを引数としてアプレットを構築します(super()を呼び出し、クラス変数を設定するオーバーロードされたコンストラクター)アプレットのinit()メソッドを呼び出します
  3. フレームを画面の中央に配置して表示します(独立したアプリケーションとして機能するため)

init()メソッドでは、他のGUIコンポーネントに加えてメニューバーを作成し、Frameのクラス変数がコンストラクターで設定されている場合は「Exit」としてJMenuItemを配置します(選択するとSystem.exit()を呼び出します) 。

これで、(チュートリアルのように)invokeAndWait()メカニズムは、アプレットUIが別のスレッドによって制御されるため、アプレットとして正常に機能します。アプリケーションとして実行します。そのSystem.exit()メソッドを呼び出すと、例外が発生します。これは、UIスレッドが終了しようとしているときに、メインスレッドが変数を保持しようとするためです。cmd / shellからアプリケーションを起動する場合、これらのJVMエラーを読み取るのは面倒です。これが、アプリケーションに推奨されない理由の1つである可能性があります。

于 2013-03-10T08:01:16.097 に答える
0

次のコードを見てください。アプレットとアプリケーションの両方として機能します。メソッド init1() と init2() は同じ UI を作成します。どちらも機能します。init2() は、ブラウザ内の他のスレッドと競合することなく、別のイベント ディスパッチ スレッドを作成します。これは、アプレットに推奨されます。ただし、これにより、[終了] ボタンをクリックしたときにスタンドアロン アプリケーションとして実行すると、時折例外が発生します。これが、アプリケーションに init1() が推奨される理由です。とにかく、これは私の理解であり、間違っている可能性があります。しかし、説明/理論的根拠は今では意味がありますか?

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;

public class P4  extends JApplet implements ActionListener {

    private Frame frame;        // null/applet, non-null/application

    public P4 () {          super();            }
    public P4 (Frame f) {       this();     frame = f;  }

    public void init () {
//      init1();        // better for application
        init2();        // better for applets
    }

    public void init1 () {
        createGUI();
    }

    public void init2 () {
        try {
                javax.swing.SwingUtilities.invokeAndWait(new Runnable() {
                public void run() {
                    createGUI();
                }
                });
        } catch (Exception ex) {
            ex.printStackTrace();
    }}

    private void createGUI () {
        JPanel p = new JPanel();
        JButton b = new JButton ("Click to say Hello to the world");
        b.addActionListener (this);
        p.add (b);
        if (frame != null) {            // application
            b = new JButton ("Exit");
            b.addActionListener (this);
            p.add (b);
            p.setPreferredSize (new Dimension (400, 50));
        }
        getContentPane().add(p);
    }

    public void actionPerformed (ActionEvent e) {
        if ("Exit".equals (e.getActionCommand()))
            System.exit (0);
        JOptionPane.showMessageDialog (frame, "Hello, world!");
    }

    public void start () { }
    public void stop () { }
    public void paint (Graphics g) { 
        super.paint (g);
    }

    public static void main (String[] args) {
        JFrame fr = new JFrame ("Appletication");
        P4 p4 = new P4 (fr);
        p4.init();      // initialize GUI
        fr.add (p4);        fr.pack();      fr.setVisible (true);
}}
于 2013-03-10T10:23:49.373 に答える
0

@trashgodしたがって、空でないstart()メソッドを入れ、回転する正方形を作成するJPanelを追加しました(start()から開始されたスレッドでアニメーション化)。init1() と init2() はまったく同じように動作することがわかりました。OP (および私自身) に、なぜこの場合に invokeAndWait() を好むのかを説明してください。

@Andrew上記の答えが正しくないことを理解しています。私が正しくない理由と、正しい答えを詳しく説明してください。私はあなたの答えの1つに従おうとしましたが、壊れたリンクに行きました.

これがコンパイル可能なアプリケーションです (はい、通常は 3 つの別々のクラスに入れますが、ここでは特定の問題に答えようとしています)。

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;

public class P4  extends JApplet implements ActionListener {

    private Frame frame;        // null/applet, non-null/application
    private Painter painter = new Painter();

    public P4 () {          super();            }
    public P4 (Frame f) {       this();     frame = f;  }

    public void init () {
//      init1();        // better for application
        init2();        // better for applets
    }

    public void init1 () {
        createGUI();
    }

    public void init2 () {
        try {
                javax.swing.SwingUtilities.invokeAndWait(new Runnable() {
                public void run() {
                    createGUI();
                }
                });
        } catch (Exception ex) {
            ex.printStackTrace();
    }}

    private void createGUI () {
        JPanel p = new JPanel(new BorderLayout());
        JButton b = new JButton ("Click to say Hello to the world");
        b.addActionListener (this);
        p.add (b, "South");
        p.add (painter, "Center");
        if (frame != null) {            // application
            b = new JButton ("Exit");
            b.addActionListener (this);
            p.add (b, "North");
        }
        getContentPane().add(p);
    }

    public void actionPerformed (ActionEvent e) {
        if ("Exit".equals (e.getActionCommand()))
            System.exit (0);
        JOptionPane.showMessageDialog (frame, "Hello, world!");
    }

    public void start () {          new Thread (painter).start(); }
    public void stop () { }
    public void paint (Graphics g) { 
        super.paint (g);
    }

    public static void main (String[] args) {
        JFrame fr = new JFrame ("Appletication");
        P4 p4 = new P4 (fr);
        p4.init();      p4.start();     // initialize GUI
        fr.add (p4);        fr.pack();      fr.setVisible (true);
    }

    public class Painter extends JPanel implements Runnable {
        private int state, px[] = new int[4], py[] = new int[4];

        public Painter () {
            super();
            setPreferredSize (new Dimension (300, 200));
        }

        public void run () {
            for ( ; ; ) {
                if (++state == 45)
                    state = 0;
                repaint();
                try {
                    Thread.sleep (25);
                } catch (InterruptedException ex) {
        }}}

        public void paint (Graphics g) {
            int w = getWidth(), h = getHeight(),
                cx = w/2, cy = h/2, halfD = (cx < cy) ? cx : cy;
            halfD -= 10;
            Graphics2D g2 = (Graphics2D) g;
            g2.setPaint (Color.white);      g2.fillRect (0,0,w,h);
            for (int i = 0 ; i < 4 ; i++) {
                double theta = (i*90 + 2*state) * Math.PI / 180;
                px[i] = (int) Math.round (cx + halfD * Math.cos (theta));
                py[i] = (int) Math.round (cy - halfD * Math.sin (theta));
            }
            g2.setPaint (Color.red);
            g2.fillPolygon (px, py, 4);
}}}
于 2013-03-10T17:22:07.603 に答える