2011-02-23 3 views
1

私は非常に愚かな質問をしてきました。コンテナフィールドへのアクセス

NetBeansを使用して小さなアプリケーションを構築していますが、次の問題があります。 私の主なクラスが順番に、私はまた、様々な(とオフトピック)の理由で延長drawingBoardと呼ばれるJPanelを含むmainAppと呼ばれ、JFrameを延長します。..

コアの問題がいくつかの点で私がする必要があるということですmainAppのフィールドの1つにアクセスしますが、NetBeansがメインクラスをインスタンス化する方法のために(匿名クラスとして)コンテナへの参照を取得できません(これがメインアプリケーションです)。

mainAppの参照を取得し、そのフィールドの値をdrawingBoardに設定するにはどうすればよいですか?

答えて

1

Window win = SwingUtilities.getWindowAncestor(myComponent);を使用してトップレベルウィンドウへの参照を取得できます。トップレベルウィンドウが最終的に保持するコンポーネントへの参照をメソッド呼び出しに渡します。あなたのメインクラスもトップレベルのJFrame(他のJFramesを初期化していない)であれば、返されたウィンドウを最上位クラスの型にキャストしてパブリックメソッドを呼び出すことができます。例えば

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

public class Foo1 { 
    public static void main(String[] args) { 
     MainApp mainApp = new MainApp(); 
     mainApp.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
     mainApp.pack(); 
     mainApp.setLocationRelativeTo(null); 
     mainApp.setVisible(true); 
    } 
} 

class MainApp extends JFrame { 
    public MainApp() { 
     getContentPane().add(new DrawingBoard()); 
    } 

    public void mainAppMethod() { 
     System.out.println("This is being called from the Main App"); 
    } 
} 

class DrawingBoard extends JPanel { 
    public DrawingBoard() { 
     JButton button = new JButton("Button"); 
     button.addActionListener(new ActionListener() { 
     public void actionPerformed(ActionEvent e) { 
      MainApp mainApp = (MainApp) SwingUtilities.getWindowAncestor(DrawingBoard.this); 
      mainApp.mainAppMethod(); 
     } 
     }); 
     add(button); 
    } 
} 

glowcoderの勧告によって行われるように変更:

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

public class Foo2 { 
    public static void main(String[] args) { 
     MainApp2 mainApp = new MainApp2(); 
     mainApp.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
     mainApp.pack(); 
     mainApp.setLocationRelativeTo(null); 
     mainApp.setVisible(true); 
    } 
} 

class MainApp2 extends JFrame { 
    public MainApp2() { 
     getContentPane().add(new DrawingBoard2(this)); 
    } 

    public void mainAppMethod() { 
     System.out.println("This is being called from the Main App"); 
    } 
} 

class DrawingBoard2 extends JPanel { 
    private MainApp2 mainApp; 

    public DrawingBoard2(final MainApp2 mainApp) { 
     this.mainApp = mainApp; 
     JButton button = new JButton("Button"); 
     button.addActionListener(new ActionListener() { 
     public void actionPerformed(ActionEvent e) { 
      buttonActonPerformed(); 
     } 
     }); 
     add(button); 
    } 

    private void buttonActonPerformed() { 
     mainApp.mainAppMethod(); 

    } 
} 

もう一つの推薦:あなたはスイングを学んでいることから、あなたが生成するためのNetBeansを使用していないオフにはるかに優れていますあなたのコードをスイングするのではなく、スイングアプリを手作業でコーディングしてください。これを行い、チュートリアルを勉強することで、Swingの仕組みをより深く理解することができます。NetBeansコードジェネレータを使用して、最も単純なアプリケーション以上のものを作成する必要がある場合に役立ちます。

+0

魅力的な作品!しかし、今では別の質問をしたばかりです...!これら2つのクラスがそれぞれJFrameとJPanelを拡張していないとどうなりますか?SwingUtilitiesを使用できなくて、Glowcoderのソリューションだけが動作するようです...!まだそれを行う別の方法があります..? – kstratis

+0

glowcoderは言及していますが、私は同意します。参照に関するものです。あるオブジェクトの参照を別のオブジェクトに渡す方法が必要であり、多くの場合、これはコンストラクタまたは設定子(ミューテータ)メソッドを通じて行われます。 –

+0

貴重なご意見をいただきありがとうございます! – kstratis

3

拡張している場合は、コンストラクタを制御できます。コンストラクタに追加することで、必要な参照を渡します(もちろん、それらをメンバー変数に割り当てることもできます)。

Yay依存性注入!

+0

こんなことはできません!目標は、アプリが起動した後、ユーザーがdrawingBoardをクリックしてから親のフィールドが更新されるまでです! – kstratis

+0

glowcoderの推奨事項は、あなたの状況ではまだ動作しますKono5(1+投票)。重要なことは、JPanelクラスにMainAppフィールドを与え、DrawingBoardコンストラクタでそれを設定することです。その後、アプリケーションの実行中、特に実行時にいつでもメソッドを呼び出すことができます。 –

+0

真...コンストラクタを介してメインクラス全体を渡しても間に合いませんでした。これも同様に動作します。 – kstratis

1

グローコーダーの回答が良いです。もう一つのオプションは、mainAppをシングルトンにすることです(論理的にはシングルトンの場合)

+0

JFrameをシングルトンにするのは良い考えではないと思います。 glowcoderが指摘するように、必要なのは単純なリファレンスだけなので、実際には必要ありません。 –