2014-08-30 1 views
1

Я пишу программу, которая выполняет следующие задачи в последовательности:Может ли событие в одном классе запускать действие в другом классе?

  1. Собирает ввод данные пользователя из JPanel
  2. использует вход для копирования зависимостей из каталога программы в новый каталог проекта
  3. Польза вход для построения интерактивного графика в каталоге проекта

У меня есть отдельный класс для каждой задачи и основной класс, который последовательно вызывает каждый объект.

Моя проблема заключается в том, что основной класс оценивает шаг 2 до завершения этапа 1. Поскольку пользователь еще не закрыл JPanel, когда основной класс вызывает объект 2, пользовательский ввод не будет собран до начала шага 2, и программа выйдет из строя.

Что мне нужно - это способ подать сигнал классу 2, что JPanel в классе 1 был закрыт. Таким образом, шаг 2 начинается с после поля ввода были собраны на этапе 1.

Есть ли способ, чтобы закрытие окна в классе 1 вызывало действие в классе 2? Если нет, то какой был бы лучший способ решить эту проблему?

+1

Вы, скорее всего, либо 1), работающие компоненты Swing, прочь из EDT, вызывая поточные вопросы или 2) не используя модальный диалог. –

+0

Я читал о потоках, и я думаю, что это может быть проблемой. Я надеялся сохранить что-то в отдельности, но я думаю, что мне просто придется все это сделать в одном классе. Для всех, кто наткнулся на это, EDT - это Тема Дискуссии о событиях, и здесь есть довольно хорошая статья: http://stackoverflow.com/questions/7217013/java-event-dispatching-thread-explanation. – Reggie

ответ

0

Трюк для общения между классами - это методы wait() и notify().

Предположим, вы выполняете метод main. В какой-то момент main вызывает другой класс, скажем, gui. Здесь вы хотите, чтобы main остановился и подождать для выполнения определенных событий в gui до main продолжается с остальными его действиями.

Это достигается за счет синхронизации блоков кода между этими двумя классами и не говоря main к wait() до графического интерфейса уведомляет его продолжить, notify(). Например:

основного

public static void main(String[] args) throws Exception { 

    GUI gui = new GUI(); 

    // Do some things 
    doSomething(); 
    doSomthingElse(); 

    // Make sure we wait until gui input has been collected before proceeding 
    synchronized(gui) { 
     try { 
      gui.wait(); 
     } 
     catch(InterruptedException e){ 
      e.printStackTrace(); 
     } 
    } 

    // Do some things using the gui input we've been waiting for   
    doSomeMoreThings(); 
} 

графического интерфейс

// The gui method we want to synchronize 
public void collectInput() { 

    synchronized(this) { 

     // Collect fields 
     name = nameField.getText(); 
     age = ageField.getText(); 
     date = dateField.getText(); 

     // Notify waiter that our business is complete 
     notify(); 
    } 
} 
4

«Есть ли способ закрыть окно в классе 1, инициировать действие в классе 2? Если нет, то каким будет лучший способ решить эту проблему?»

Как указал Борис Паук, вы должны использовать диалоговое окно модели. Вероятно, вы используете фрейм. Вы должны прочитать Modality, чтобы узнать его поведение и особенности. Также потребуется некоторое время, чтобы посмотреть на How to make Dialogs. Короче говоря, включение модальности диалога (которое по умолчанию используется для JOptionPane статических методов showXxx и может быть установлено на JDialog либо через setModalityType, либо через constructor), поток будет «блокироваться» до тех пор, пока диалог не будет закрыт.

Ниже приведен пример. Это может быть слишком сложно для такой простой задачи (как это легко может быть достигнуто с помощью JOptionPane), но он показывает, как использовать JDialog. Посмотрите, как класс ShowDialogActionListener. Диалог устанавливается видимым, и поток не продолжается в actionPerformed до тех пор, пока диалог не будет закрыт, а именно, когда в диалоговом окне получено Input.

import java.awt.GridBagLayout; 
import java.awt.GridLayout; 
import java.awt.event.ActionEvent; 
import java.awt.event.ActionListener; 

import javax.swing.JButton; 
import javax.swing.JDialog; 
import javax.swing.JFrame; 
import javax.swing.JPanel; 
import javax.swing.JTextField; 
import javax.swing.SwingUtilities; 

public class DialogDemo { 
    private JFrame frame = new JFrame(); 

    public DialogDemo() { 
     JButton button = new JButton("Open Dialog"); 
     button.addActionListener(new ShowDialogActionListener()); 
     frame.setLayout(new GridBagLayout()); 
     frame.add(button); 
     frame.setSize(300, 300); 
     frame.setLocationRelativeTo(null); 
     frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
     frame.setVisible(true); 
    } 

    class ShowDialogActionListener implements ActionListener { 

     @Override 
     public void actionPerformed(ActionEvent e) { 
      InputDialog dialog = new InputDialog(frame, true); 
      System.out.println("Opened dialog....."); 

      long start = System.currentTimeMillis(); 
      dialog.setVisible(true); 
      System.out.println("Dialog closed after " 
        + (System.currentTimeMillis() - start) + " ms"); 

      Input input = dialog.getInput(); 
      ServiceOne service = new ServiceOne(); 
      service.serviceMethod(input); 
     } 
    } 

    class ServiceOne { 
     public void serviceMethod(Input input) { 
      System.out.println(input.getInput()); 
     } 
    } 

    class InputDialog extends JDialog { 
     private Input input; 

     public InputDialog(JFrame parent, boolean modal) { 
      super(parent, modal); 

      JPanel panel = new JPanel(new GridLayout(0, 1)); 
      final JTextField field = new JTextField(20); 
      JButton okButton = new JButton("OK"); 
      panel.add(field); 
      panel.add(okButton); 

      okButton.addActionListener(new ActionListener() { 
       public void actionPerformed(ActionEvent e) { 
        String text = field.getText(); 
        input = new Input(); 
        input.setInput(text); 
        InputDialog.this.dispose(); 
       } 
      }); 

      setLayout(new GridBagLayout()); 
      add(panel); 
      setSize(250, 250); 
      setLocationRelativeTo(parent); 
     } 

     public Input getInput() { 
      return input; 
     } 
    } 

    class Input { 
     private String input = "default"; 

     public void setInput(String input) { 
      this.input = input; 
     } 

     public String getInput() { 
      return input; 
     } 
    } 

    public static void main(String[] args) { 
     SwingUtilities.invokeLater(new Runnable() { 
      public void run() { 
       new DialogDemo(); 
      } 
     }); 
    } 
} 

Как я уже говорил ранее, то же самое можно было бы легко осуществить с

String input = JOptionPane.showInputDialog("Enter a Message"); 

Приведенный выше будет также блокировать выполнение потока.

+0

Думаю, вы, возможно, неправильно поняли мой вопрос. Я запустил код, который вы предоставили, и он почти точно выполняет мою программу в настоящий момент - открывает родительское окно, открывает всплывающее окно при нажатии кнопки в родительском окне и регистрирует всплывающее окно ввода, когда pop -up закрывается. Что мне нужно - это способ затем передать отдельный класс (класс, из которого вызывается родительское окно), что окно _parent_ было закрыто. В противном случае класс, который вызвал входной gui, пытается выполнить остальные его задачи до того, как наборы gui действительно собраны. – Reggie

+0

Будет намного проще рассказать, о чем вы говорите, с помощью какого-то кода. Пожалуйста, отредактируйте свое сообщение с соответствующим кодом –

+0

Если бы был краткий способ показать вам какой-то код, я бы это сделал :) Но я понял, что ему пришлось использовать wait() и notify(). – Reggie

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