2014-08-30 30 views
1

我正在寫的順序完成以下任務的程序:一個類中的事件是否可以在另一個類中觸發一個動作?

  1. 收集來自一個JPanel
  2. 用戶輸入使用輸入對從程序目錄複製依賴到一個新的項目目錄
  3. 用途在項目目錄中構建交互式圖形的輸入

我有一個單獨的類,用於每個任務和一個主要類,它們按順序調用每個對象。

我的問題是,主類在步驟1完成之前評估步驟2。由於用戶在主類調用對象2時尚未關閉JPanel,因此在步驟2開始之前並未收集用戶輸入並且程序崩潰。

我需要的是向第2類發信號通知第1類中的JPanel已關閉的方法。這樣步驟2開始後輸入字段已被收集在步驟1

有一種方法,以具有在1個觸發器的窗口關閉在2類的動作?如果不是,解決這個問題最好的辦法是什麼?

+1

你最有可能:1)運行關閉EDT的Swing組件,從而導致線程問題或2)不使用模態對話。 – 2014-08-30 16:47:52

+0

我讀了線程,我認爲這可能是問題。我希望把事情分開,但我想我只需要把它放在一個班級。對於其他人而言,EDT是Event Dispatch Thread,這裏有一篇相當不錯的文章:http://stackoverflow.com/questions/7217013/java-event-dispatching-thread-explanation。 – Reggie 2014-09-03 23:21:00

回答

0

在類之間傳遞事件的技巧是wait()notify()方法。

假設您正在執行main方法。在某個點main調用另一個班級,比如gui。在這裏,您需要main暫停,等待在gui中的某些事件完成之前main繼續其餘的行動。

這是通過同步兩個類之間的碼塊,並告訴mainwait()直到GUI 完成通知它繼續,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(); 
} 

GUI

// 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層的動作?如果沒有,解決這個問題最好的辦法是什麼?

正如Boris the Spider指出的那樣,您應該使用模型對話框。你可能正在使用一個框架。您應該閱讀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

我想你可能誤解了我的問題。我運行了你提供的代碼,它幾乎完全符合我目前的程序 - 打開一個父窗口,當父窗口中的一個按鈕被點擊時打開一個彈出窗口,並且在彈出窗口時記錄彈出窗口輸入關閉。 我需要的是一種方法,然後通信到一個單獨的類(調用父窗口的類)_parent_窗口已關閉。否則,在gui輸入實際收集之前,調用輸入gui的類將嘗試執行其餘任務。 – Reggie 2014-09-03 23:14:35

+0

用一些代碼來講述你正在談論的內容會容易得多。請編輯您的文章,並附上一些相關的代碼 – 2014-09-04 01:43:17

+0

如果有簡明的方式向您展示一些代碼,我會有:)但我想通了 - 只好使用wait()和notify()。 – Reggie 2014-09-06 16:04:14

相關問題