【问题标题】:Accessing container fields访问容器字段
【发布时间】:2011-07-02 11:26:36
【问题描述】:

我有一个非常愚蠢的问题要问。

我正在使用 NetBeans 构建一个小应用程序,但遇到以下问题; 我的主要课程称为mainApp,并且正在扩展一个JFrame,而JPanel 又包含一个名为drawingBoarddrawingBoard,我也出于各种(和离题的)原因对其进行了扩展..

核心问题是,在某些时候我需要访问 mainApp 的字段之一,但由于 NetBeans 实例化我的主类的方式..(作为匿名类)我无法获得对容器(这是我的 mainApp)。

如何获取mainApp 的引用并在drawingBoard 中设置其字段的值?

【问题讨论】:

    标签: java components containers parent anonymous-class


    【解决方案1】:

    您可以通过使用 Window win = SwingUtilities.getWindowAncestor(myComponent); 来获取对顶级窗口的引用。并将对顶层窗口最终拥有的任何组件的引用传递给方法调用。如果您的主类也是您的顶级 JFrame(您没有初始化任何其他 JFrame),那么您可以将返回的 Window 转换为您的顶级类类型并调用其公共方法。

    例如:

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

    另一个建议:由于您正在学习 Swing,因此最好不要使用 NetBeans 为您生成 Swing 代码,而是手动编写 Swing 应用程序。通过这样做并学习教程,您将对 Swing 的工作原理有更深入和更好的理解,并且如果您需要使用 NetBeans 代码生成器来制作最简单的应用程序之外的任何东西,它将为您提供帮助。

    【讨论】:

    • 像魅力一样工作!但是现在您又提出了另一个问题..!如果这两个类没有分别扩展 JFrame 和 JPanel 怎么办..?您不应该使用 SwingUtilities 并且似乎只有 Glowcoder 的解决方案可以工作...!会还有另一种方法吗..?
    • 正如 Glowcoder 提到的,我同意,这都是关于引用的——必须有一种方法可以将一个对象的引用传递给另一个对象,并且通常通过构造函数或 setter(mutator)方法来完成。
    • 非常感谢您的宝贵意见!
    • 最后一点,我完全按照你的建议尝试了 Glowcoder 的方法,你猜怎么着!它使netbeans表单编辑器崩溃!就试一试吧!这可能是一个真正的错误!
    • 这完全取决于您如何尝试。魔鬼在细节中。
    【解决方案2】:

    Glowcoder 的回答很好。另一种选择是使 mainApp 成为单例(如果是,从逻辑上讲,单例)

    【讨论】:

    • 我认为将 JFrame 设为单例并不是一个好主意。确实没有必要,因为所需要的只是一个简单的参考,正如 Glowcoder 指出的那样。
    【解决方案3】:

    如果你正在扩展,你可以控制构造函数。通过将它们添加到构造函数(当然,将它们分配给成员变量)来传递您需要的任何引用。

    是的依赖注入!

    【讨论】:

    • 不...不能那样做..!目标是在应用程序启动后,用户点击绘图板,然后父字段才会更新..!
    • glowcoder 的建议仍然适用于您的情况 Kono5(1+ 票)。关键是给 JPanel 类一个 MainApp 字段并在 DrawingBoard 构造函数中设置它。然后,您可以在应用运行期间的任何时间调用其方法,尤其是在运行时。
    • 是的......我没想到通过构造函数传递整个主类......它也可以这样工作......
    猜你喜欢
    • 2011-07-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-05-05
    • 1970-01-01
    相关资源
    最近更新 更多