2015-09-08 89 views
0

我有一些Java類應該模擬舊的計算機器。其中一個是JFrame,名爲GUI,帶有JTabbedPane。計算過程需要一些時間,所以我已經包含了Thread.sleep(int)。問題是,在計算功能正在工作時,我的GUI中的JTabbedPane的選項卡無法選擇。JFrame在Thread.sleep期間處於非活動狀態(int)

下面是一些代碼:

import java.util.*; 
import java.awt.*; 

public class Engine 
{ 
    private GUI gui; 
    private Store store; 
    private Mill mill; 

    public static void main(String[] args) { 
     Engine e = new Engine(); 
    } 

    public Engine() { 
     gui = new GUI(this); 
     mill = new Mill(this); 
     store = new Store(this); 

     store.draw();      // affects GUI elements 
    } 

    public void read(String operations) { 
     clearStatus();      // affects GUI elements 

     try { 
      String[] op = operations.split("\n"); 

      for (int i = 0; i < op.length; i++) { 
       setStatus(op[i]);  // affects GUI elements 

       if (op[i].length() == 0) { // empty line 
        continue; 
       } 

       int number = Integer.parseInt(op[i]); 
       store.addNumber(number); 

       Thread.sleep(200); 
      } 

      store.draw();     // affects GUI elements 

     } catch(Exception e) { 
      System.out.println(e); 
     } 
    } 

    public void clearStatus() { 
     gui.statusLabel.setText(""); 
    } 

    public void setStatus(String msg) { 
     gui.statusLabel.setText(msg); 
    } 
} 

這裏是我的GUI(這是一個短版):

import java.awt.*; 
import java.awt.event.*; 
import javax.swing.*; 

public class GUI extends JFrame 
{ 
    private Engine engine; 

    // Swing 
    JTabbedPane tabs; 
    JPanel mill; 
    JTextArea input, store; 
    JLabel statusLabel; 
    JButton sendInput; 

    public GUI(Engine e) 
    { 
     engine = e; 

     input = new JTextArea(); 
     sendInput = new JButton("Run"); 
     sendInput.addActionListener(new ActionListener() { 
      public void actionPerformed(ActionEvent evt) { 
       pressInputButton(evt); 
      } 
     }); 

     JPanel inputPanel = new JPanel(); 
     inputPanel.add(input,  BorderLayout.CENTER); 
     inputPanel.add(sendInput, BorderLayout.SOUTH); 

     mill = new JPanel(); 
     statusLabel = new JLabel(); 
     mill.add(statusLabel); 

     store = new JTextArea(); 

     JTextPane helpPane = new JTextPane(); 
     helpPane.setText("[...]"); 

     tabs = new JTabbedPane(); 
     tabs.addTab("Input", inputPanel); 
     tabs.addTab("Mill", mill); 
     tabs.addTab("Store", new JScrollPane(store)); 
     tabs.addTab("Help", helpPanel); 

     add(tabs, BorderLayout.CENTER); 
     setVisible(true); 
     pack(); 
    } 

    public void pressInputButton(ActionEvent evt) { 
     engine.read(input.getText()); 
    } 
} 
+3

不應該說'JFrame'和'Thread.sleep'這兩個術語;) – Reimeus

+3

Thread.sleep會鎖定你的整個線程,如果你希望你的JFrame繼續運行,你需要做所有的模擬代碼另一個線程,只有把線程睡覺。永遠不要睡覺你的JFrame線程。 – sorifiend

+0

可能的重複與您的問題不完全相同,但這是因爲相同的問題。基本上,當你在長時間運行的事件派發線程上執行某些操作時,GUI本身不允許運行。 – resueman

回答

4

什麼@sorifiend的意思是,從事件處理程序調用sleep()會「鎖定「您的應用程序的事件調度線程。在事件處理函數返回之前,應用程序不會響應任何其他用戶輸入。

如果您希望應用程序響應,而計算器「工作」,那麼你需要做的是:

  • 記錄對計算器的狀態是「工作」
  • 禁止任何在計算器正在「工作」時不希望用戶按下按鈕, - 或者 - 如果在「正在工作」時按下這些按鈕,則可以更改這些按鈕的處理程序以執行不同的操作(模擬卡住機器?)州。
  • 在不久的將來提交的定時器事件的一段時間(但長的計算應該採取。)
  • 在處理程序中的定時器事件,顯示計算的結果,重新啓用被禁用的按鈕,並將狀態從「工作」改回「空閒」(或其他)。
+0

適當地比它的價值更麻煩,但另一個可能的解決方法而不是禁用按鈕是覆蓋用戶不應該與之交互的區域頂部的單個玻璃板,然後使其消耗所有用戶鼠標事件,這可能比禁用多個組件。 (如果採取這種方法,不要忘記使用可以繞過玻璃窗格的標籤鍵等按鍵事件) – sorifiend

相關問題