5

私は今、Java GUIの基礎を学んでいます。私は本当に説明できないこの奇妙な状況を抱えています。

シンプルなJFrameを構築するGUIクラスがあります。.setVisible(true) コンストラクター内で使用するとすべて正常に動作し、外部で使用すると何も読み込まれません(ウィンドウは表示されますが、ボタンとそうでないものは表示されません)。

なぜこうなった ?

public class GUI extends JFrame {


    private JTextField humanYears_TextField = new JTextField(3);
    private JTextField dogYears_TextField = new JTextField(3);
    private JButton convert_Button = new JButton("Convert");
    private JLabel greeting = new JLabel ("Dog years to Human years!");

    public GUI () {

        JFrame window = new JFrame();
        JPanel content = new JPanel();


        content.setLayout(new FlowLayout());
        content.add(this.greeting);
        content.add(new JLabel("Dog Years: "));
        content.add(this.dogYears_TextField);
        content.add(this.convert_Button);
        content.add(new JLabel("Human Years: "));
        content.add(this.humanYears_TextField);

        window.setContentPane(content);
        pack(); // aplica contentPane-ul
        window.setLocationRelativeTo(null);

        window.setTitle("Dog Year Converter");
        window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        window.setVisible(true); // IF IT'S HERE IT WORKS
    }
}

public static void main(String[] args) {

    GUI dogYears = new GUI();
    //dogYears.setVisible(true); // IF IT'S HERE
                                 //NOTHING EXCEPT THE WINDOW LOADS
}

なぜこうなった ?

この例では問題ありませんが、ボタンなどをクリックした場合にのみウィンドウを表示したい場合はどうすればよいでしょうか?

4

5 に答える 5

7

1)最初のインスタンスをクラスのJFrame 拡張から作成し、2番目のインスタンスをから作成します。あなたは続けてを呼び、あなたのメインであなたはあなたを呼び込もうとします。JFrameJFrame window=..setVisible(..)windowsetVisible(...)dogYears

解決

SwingGUIごとに1つだけ作成する必要がありますJFrame。Swingでextends JFrame拡張するのは良い習慣ではないので、(およびそれに付随するコード)を取り除きます。JFrameしたがって、もちろんsetVisible(true)、コンストラクターでGUIを作成した後に呼び出すか、 sメソッドのsetVisibleラッパーとなるGUIクラスのようなメソッドを作成することで、コンストラクターを呼び出すことはできません。JFramesetVisble(boolean b)

その他の提案

  • 常にSwingコンポーネントを作成し、ブロックEvent Dispatch Threadを介して実行する必要があります。Swingの並行性SwingUtilitites.invokeLater(Runnable r)について読んでください。

  • JFrame表示を設定する前、およびコンポーネントを追加した後は、必ずパックを呼び出してください。

  • setLocationRelativeTo(..)後に来る必要がありますpack()

  • JFrame.DISPOSE_ON_CLOSEタイマーを使用しない限り、使用することをお勧めします。

  • また、単にインスタンスをsetContentPane呼び出す必要もありません。add(..)JFrame

上記の修正を加えたコードは次のとおりです。

ここに画像の説明を入力してください

import java.awt.FlowLayout;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.SwingUtilities;

public class GUI {

    private JTextField humanYears_TextField = new JTextField(3);
    private JTextField dogYears_TextField = new JTextField(3);
    private JButton convert_Button = new JButton("Convert");
    private JLabel greeting = new JLabel("Dog years to Human years!");
    private JFrame window = new JFrame();
    private JPanel content = new JPanel();

    public GUI() {
        content.setLayout(new FlowLayout());
        content.add(this.greeting);
        content.add(new JLabel("Dog Years: "));
        content.add(this.dogYears_TextField);
        content.add(this.convert_Button);
        content.add(new JLabel("Human Years: "));
        content.add(this.humanYears_TextField);

        window.add(content);

        window.setTitle("Dog Year Converter");
        window.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);

        window.pack();
        window.setLocationRelativeTo(null);
        //window.setVisible(true); //works here now
    }

    //our wrapper method so we can change visibility of our frame from outside the class
    void setVisible(boolean visible) {
        window.setVisible(visible);
    }

    public static void main(String[] args) {
        //Create Swing components on EDT
        SwingUtilities.invokeLater(new Runnable() {
            @Override
            public void run() {
                GUI dogYears = new GUI();
                dogYears.setVisible(true);//works here too
            }
        });
    }
}
于 2013-01-30T12:22:16.537 に答える
5

JFrameGUIクラス自体と内部変数「window」の2つがあります。1つだけ使用してください。

GUIが拡張されていないことを確認しJFrame(これは必要ありません)、ウィンドウを表示に設定するpublicvoidsetVisible(boolean)メソッドをクラスに与えます。

public class GUI {


    private JTextField humanYears_TextField = new JTextField(3);
    private JTextField dogYears_TextField = new JTextField(3);
    private JButton convert_Button = new JButton("Convert");
    private JLabel greeting = new JLabel ("Dog years to Human years!");
    private JFrame window = new JFrame();

    public GUI () {

        JPanel content = new JPanel();


        content.setLayout(new FlowLayout());
        content.add(this.greeting);
        content.add(new JLabel("Dog Years: "));
        content.add(this.dogYears_TextField);
        content.add(this.convert_Button);
        content.add(new JLabel("Human Years: "));
        content.add(this.humanYears_TextField);

        window.setContentPane(content);
        pack(); // aplica contentPane-ul
        window.setLocationRelativeTo(null);

        window.setTitle("Dog Year Converter");
        window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        // window.setVisible(true); // IF IT'S HERE IT WORKS
    }

    public void setVisible(boolean visible) {
        window.setVisible(visible);
    }
}
于 2013-01-30T12:23:18.107 に答える
4

2つの異なるインスタンスがあります:-)

コンストラクター内:

JFrame window = new JFrame();
window.setVisible(true); // IF IT'S HERE IT WORKS

あなたのメインで:

GUI dogYears = new GUI();
dogYears.setVisible(true); 
// dogYears != local var window in constructor

これで、クラスを拡張するのではなく、使用するようになるかもしれません。

于 2013-01-30T12:22:45.220 に答える
2

あなたのクラスGUIは a から拡張されてJFrameいますが、コンストラクターでは別の JFrame を初期化しているため、2 つの異なる JFramesが発生します。

これを試して:

public class GUI {

    private JTextField humanYears_TextField = new JTextField(3);
    private JTextField dogYears_TextField = new JTextField(3);
    private JButton convert_Button = new JButton("Convert");
    private JLabel greeting = new JLabel ("Dog years to Human years!");

    public GUI () {
        JFrame window = new JFrame();
        JPanel content = new JPanel();

        content.setLayout(new FlowLayout());
        content.add(this.greeting);
        content.add(new JLabel("Dog Years: "));
        content.add(this.dogYears_TextField);
        content.add(this.convert_Button);
        content.add(new JLabel("Human Years: "));
        content.add(this.humanYears_TextField);

        window.setContentPane(content);
        pack(); // aplica contentPane-ul
        window.setLocationRelativeTo(null);

        window.setTitle("Dog Year Converter");
        window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        window.setVisible(true);
    }

    // main

}
于 2013-01-30T12:25:23.793 に答える
0

JFRameも拡張するGUIのコンストラクターでJFrameのインスタンスを作成しています。ここで、さまざまなコンポーネントを作成し、それらを「window」オブジェクトに追加しました。ご存じのとおり、フレームは visible= false および undecorated=false に設定されています。したがって、特定の JFrame インスタンスを設定するには、そのインスタンスで setVisible() メソッドを呼び出す必要があります。

ここでは、GUI のインスタンスを作成しているだけで、コンポーネントを追加していません。「window.setContentPane(content);」ではなく、次のようにコンストラクターにステートメントを記述します。:

setContentPane(コンテンツ);

次に、GUI クラスのインスタンスで setVisible() メソッドを呼び出します。つまり、d* ogYears.setVisible(true); *!!

于 2013-01-30T12:38:18.543 に答える