2011-02-23 3 views
1

У меня вопрос очень глупый.Доступ к полям контейнеров

Я использую NetBeans для создания небольшого приложения, и у меня возникает следующая проблема; Мой главный класс называется mainApp и протягивает JFrame, который в свою очередь, содержит JPanel называется drawingBoard, который я также продлить на различных (и не по теме) причинам ..

Основная проблема заключается в том, что в какой-то момент мне нужно получить доступ к одному из полей mainApp, но из-за того, как NetBeans создает экземпляр моего основного класса .. (как анонимный класс) Я не могу получить ссылку на контейнер (это мой mainApp).

Что я могу сделать, чтобы получить ссылку от mainApp и установить значение его поля в пределах drawingBoard?

ответ

1

Вы можете получить ссылку на окно верхнего уровня, используя Window win = SwingUtilities.getWindowAncestor (myComponent); и, перейдя в метод, вызовите refrence любому компоненту, который в конечном итоге имеет окно верхнего уровня. Если ваш основной класс также является вашим 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-код для вас, а скорее для кодирования ваших приложений Swing вручную. Делая это и изучая учебники, вы получите гораздо более глубокое и лучшее понимание того, как работает Swing, и это поможет вам, если вам нужно использовать генератор кода NetBeans, чтобы сделать что-то большее, чем самые простые приложения.

+0

Работает как очарование! Но теперь вы только что спровоцировали другой вопрос ..! Если бы эти два класса не распространяли JFrame и JPanel соответственно ..? Вы не должны использовать SwingUtilities, и кажется, что только решение Glowcoder будет работать ...! есть еще один способ сделать это.? – kstratis

+0

Как упоминалось glowcoder, и я согласен, все дело в ссылках - должен быть способ передать ссылки одного объекта другому, и часто это делается с помощью методов конструктора или сеттера (мутатора). –

+0

Большое вам спасибо за бесценный ввод! – kstratis

3

Если вы расширяетесь, вы можете управлять конструктором. Передайте любые необходимые вам ссылки, добавив их в конструктор (и, конечно же, присвоив их переменным-членам).

Yay зависимость!

+0

nope ... не можем этого ..! Цель заключается в том, что после запуска приложения пользователь нажимает на drawingBoard и только THEN поле родителя обновляется ..! – kstratis

+0

Рекомендация glowcoder по-прежнему работает для вашей ситуации Kono5 (1+ голосов). Ключ должен дать классу JPanel поле MainApp и установить его в конструкторе DrawingBoard. Затем вы можете вызывать его методы в любое время во время запуска вашего приложения, в том числе и особенно во время выполнения. –

+0

Истинный ... не переходил мой разум, передавая весь основной класс через конструктор. Он также может работать так же. – kstratis

1

Ответ на Glowcoder - это хорошо. Другой вариант - сделать mainApp a Singleton (если это так, логически говоря, Singleton)

+0

Я не думаю, что это хорошая идея сделать JFrame синглом. Там действительно не нужно, поскольку все, что необходимо, - это простая ссылка, как указывает glowcoder. –

Смежные вопросы