Swing — вызывающие события из внутренней панели

#java #swing #jframe #jbutton #actionlistener

#java #swing #jframe #jbutton #actionlistener

Вопрос:

У меня простой Swing GUI с главным окном JFrame , и его основная панель является производной от JPanel . На панели есть несколько кнопок, которые можно нажимать и генерировать события.

Я хочу, чтобы эти события влияли на данные, хранящиеся в JFrame , потому что это мое основное приложение — в нем есть несколько очередей для потоков, открытых потоков и так далее.

Итак, как мне заставить мою кнопку в панели вызывать обратные вызовы в ее родительском фрейме? Как лучше всего использовать это для Java / Swing?

Ответ №1:

Для вызова методов в родительском фрейме вам нужна ссылка на родительский фрейм. Итак, конструктор вашей JPanel может быть объявлен следующим образом:

  public MyPanel(MyFrame frame){
    super();
    this.frame = frame;
    //the rest of your code
}
  

И в JFrame вы вызываете этот конструктор следующим образом:

   panel = new MyPanel(this);//this refers to your JFrame
  

В обработчиках событий, прикрепленных к вашим кнопкам, теперь у вас есть доступ к фрейму и вы можете вызывать различные методы по мере необходимости.

   button1.addActionListener(new ActionListener(){
      public void actionPerformed(ActionEvent e){
           //do some stuff
           frame.someMethod();//invoke method on frame
           //do more stuff
      }
  });
  

Ответ №2:

Взгляните на это руководство по использованию SwingWorker.

Комментарии:

1. почему это помогает мне? Я просто хочу получить чистый доступ к JFrame из JPanel, который он содержит

2. извините, это было неясно. вы можете использовать SwingUtilities.getWindowAncestor( JPanel ) для получения родительского окна

Ответ №3:

Используйте метод addActionListener для желаемых кнопок, указывающих класс, реализующий ActionListener.

 ActionListenerClass actionListenerObject = new actionListenerClass();
JButton b = new JButton("Button");
b.addActionListener(actionListenerObject);

public class ActionListenerClass implements ActionListener(){
 //or better : actionListenerClass extends AbstractAction
      public void actionPerformed(ActionEvent e) {
      }
}
  

Редактировать:

Да, я это знаю. Но прослушивателем действий я хочу быть в родительском классе JFrame — в этом проблема

затем расширяет класс JFrame, создавая новый производный класс, реализующий желаемый интерфейс.

Комментарии:

1. Да, я это знаю. Но прослушивателем действий я хочу быть в родительском классе JFrame — в этом проблема

Ответ №4:

Вы можете реализовать ActionListener в своем классе, который имеет JFrame (или расширяет его):

 class MyPanelClass {
    public MyPanelClass(ActionListener al)
    {
        //...
        JButton myButton = new JButton("Button");
        myButton.addActionListener(al);
        //...
    }
}
  

 class MainClass extends JFrame implements ActionListener {
    public void someMethod() {
        MyPanelClass mpc = new MyPanelClass(this);
    }

    @Override
    public void ActionPerformed(ActionEvent ev) {
        // your implementation
    }
}
  

Комментарии:

1. Но тогда нужно демультиплексировать все кнопки, которые были вызваны в нем, верно? все достигают одного и того же actionPerformed обратного вызова?

2. Это правильно. И я вижу проблему, о которой вы говорите. Возможно, передача фрейма — лучший вариант…