2015-09-08 2 views
0

У меня есть некоторые классы Java, которые должны имитировать старую вычислительную машину. Одним из них является JFrame, называемый GUI, с JTabbedPane. Процесс вычисления займет некоторое время, поэтому я включил Thread.sleep (int). Проблема в том, что пока функция вычисления работает, вкладки 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

Этот дубликат не совсем такой же, как и ваша проблема, но из-за той же проблемы. В основном, когда вы что-то делаете в Thread Dispatch Thread, который выполняется в течение длительного времени, сам GUI не может запускаться. – resueman

ответ

4

Что @sorifiend означает, вызов sleep() из обработчика событий будет " заблокировать "приложение вашего приложения. Приложение не будет отвечать на любой другой ввод пользователя до тех пор, пока функция обработчика события не вернется.

Если вы хотите, чтобы приложение будет реагировать в то время как калькулятор «работает», то, что вам нужно сделать, это:

  • запись о том, что состояние калькулятора «работает»
  • Отключить все, кнопки, которые вы не хотите, чтобы пользователь нажал, пока калькулятор «работает», - OR-- измените обработчики для этих кнопок, чтобы сделать что-то другое (имитируйте заклинивание машины?), если они нажаты во время «работы», государство.
  • Отправьте событие таймера на какое-то время в ближайшем будущем (как бы долго он не принимался.)
  • В обработчике события таймера отобразите результат вычисления, снова включите отключенные кнопки, и измените состояние с «рабочего» на «холостой» (или что-то еще).
+0

Правильно больше хлопот, чем его ценность, но еще одна возможная обходная кнопка, а не отключить кнопки - это наложение на один стеклянное стекло сверху области, с которой пользователь не должен взаимодействовать, а затем заставить его потреблять все события мыши пользователя, это может быть проще, чем отключить несколько компоненты. (если вы примете этот подход, не забудьте использовать ключевые события нажатия клавиш, например, клавишу вкладки, которая может обходить стеклянную панель) – sorifiend

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