开发者

Accessing container fields

I've got a very silly question to ask.

I'm using NetBeans to built a small app and I'm having the following problem; My main class is called mainApp and is extending a JFrame which in turn contains a JPanel called drawingBoard which I also extend for various (and off-topic) reasons..

The core problem is that at some point I need to access one of the fields of the mainApp but due to the way NetBeans instantiates my main class..(as anonymous class) I can't get a reference to the cont开发者_开发问答ainer(that is my mainApp).

What can I do to get a reference of mainApp and set the value of its field within drawingBoard?


If you're extending, you have control over the constructor. Pass in whatever references you need by adding them to the constructor (and assigning them to member variables, of course.)

Yay dependency injection!


You can get a reference to the top level window by using Window win = SwingUtilities.getWindowAncestor(myComponent); and passing into the method call a refrence to any component that the top level window ultimately holds. If your main class is also your top level JFrame (you're not initializing any other JFrames), then you can cast the returned Window to your top level class type and call its public methods.

For example:

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

altered to be done by glowcoder's recommendation:

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

   }
}

Another recommendation: since you're learning Swing, you're far better off not using NetBeans to generate Swing code for you but rather to code your Swing apps by hand. By doing this and studying the tutorials, you'll gain a far deeper and better understanding of just how Swing works, and it will help you should you need to use the NetBeans code generator to make anything more than the most simple of apps.


Glowcoder's answer is good. The other option is to make mainApp a Singleton (if it is, logically speaking, a Singleton)

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜