2017-01-25 13 views
0

申し訳ありませんが、スレッドを使用するのは初めてです。Java Swing GUI - スレッドを常時スリープ状態にして、クリックで目を覚ます方法は?

私は、Parlamiクラスのスレッドをスリープ状態にして、actionListenerでのみ起動できるようにします。

私はこの方法を試みましたが、機能していない、彼はまだ眠っています。 スレッドをこの方法で使用するのは正しいですか、wait()を使用する必要がありますか?

package parlami; 

import java.util.logging.Level; 
import java.util.logging.Logger; 

/** 
* 
* @author giacomofava 
*/ 
public class Parlami 
{ 
    public boolean finito = false; 
    public String s=""; 

    public void ascolta() 
    { 
     int i=0; 
     while (i<=1500) 
     { 
      // dormi 50 millisecondi 
      try 
      { 
       Thread.sleep(50); 
       i+=40; 
      } 
      catch (InterruptedException e) 
      { 
      } 

      while (voce.SpeechInterface.getRecognizerQueueSize() > 0) 
      { 
       s = s+"\n"+voce.SpeechInterface.popRecognizedString(); 
      } 
     } 
    } 

    public String scrivi() 
    { 
     return "Hai detto: "+s; 
    } 

    public void leggi() 
    { 
     voce.SpeechInterface.synthesize(s); 
    } 

    public void dormi(int milli) 
    { 
     try 
     { 
      System.out.println("i'm sleeping"); 
      Thread.sleep(milli); 
     } 
     catch (InterruptedException ex) 
     { 
      System.out.println("i'm awake "); 
      ascolta(); 
     } 
    } 
} 

これはGUIです:あなたはスイングイベントスレッド上Thread.sleepを呼び出した場合、あなたは役に立たない、それをレンダリングするスリープ状態にアプリケーション全体を配置します

public class GUI extends JFrame 
{ 
    private Parlami p; 
    private JPanel nord, centro; 
    private JButton registra, leggi; 
    private JTextArea display; 

public static void main(String[] args) 
{ 
    new GUI(); 
} 

public GUI() 
{ 
    p=new Parlami(); 
    initComponents(); 
} 

private void initComponents() 
{ 
    voce.SpeechInterface.init("./lib", true, true,"./lib/gram", "vocabolario"); 

    // N O R D 
    nord=new JPanel(); 
    display=new JTextArea(""); 
    display.setForeground(Color.GREEN); 
    display.setBackground(Color.BLACK); 
    nord.setBackground(Color.BLACK); 
    nord.add(display); 

    // C E N T R O 
    centro=new JPanel(); 
    registra=new JButton("tieni premuto per registrare"); 
    registra.addActionListener(new ActionListener() { 
     @Override 
     public void actionPerformed(ActionEvent e) 
     { 
      Thread.currentThread().interrupt();// <-------- HERE I TRY TO AWAKE HIM 
      display.setText(p.scrivi()); 
     } 

    }); 

    centro.add(registra); 
    leggi=new JButton("leggi"); 
    centro.add(leggi); 

    this.setLayout(new BorderLayout()); 
    this.add(nord, BorderLayout.NORTH); 
    this.add(centro, BorderLayout.CENTER); 
    this.setSize(700,300); 
    this.setDefaultCloseOperation(EXIT_ON_CLOSE); 
    this.setVisible(true); 
    p.dormi(50000); // <-------- HERE I TELL HIM TO SLEEP 

} 
} 
+0

代わりo'Thread.currentThread(に適している))、(中断; '、していますあなたはp.interrupt()を試しましたか? 'Parlami'は別個のスレッドでなければなりません(つまり、Runnableを実装することによって)。また、私はそれがとにかく40msだけ眠っていることに気付きます。私は待機/通知を使用します。 –

+0

「ロック」については、「オブジェクトのロック」(https://docs.oracle.com/javase/tutorial/essential/concurrency/newlocks.html)から始めることをお勧めします。アイデアは " 1つのスレッドのロックで「待機」し、ロックの同じインスタンスを使用して、「通知する」は、処理しなければならない更新が発生したことを監視します。スイングはシングルスレッドであることを覚えておいてください。(ロックオブジェクトを待つような)EDT上でアクションを実行しないでください。EDT内からUIを更新するだけです。 – MadProgrammer

+0

はい、私はすでにparlami.interruptで試しています。 ():( –

答えて

5

が、もっと重要なのは、実行する必要はありませんこの。 ActionListenerは、イベントドリブンプログラミングの仕組みであるため、アクティベーションが必要なオブジェクトをアクティブ化するだけです。

Swingアプリケーションで遅延が必要な場合は、このサイトで何度も繰り返し議論されているSwing Timerを使用してください。

2

これは、スレッドロックのトピックに関連付けられたスレッド待機/通知の基本概念です。基本的には、 "ロック"の役割を果たす共通のオブジェクトがあり、このスレッドでは1つのスレッドが "待機"し、別のスレッドが必要な場合は、何らかのアクションが発生したことをモニターに通知します。

詳細はLock Objectsをご覧ください。

以下は、概念の非常に基本的な例です。Threadは継続的に実行できますが、共通のロックで「待機」しています。ボタンのActionListenerは再び、

「待つ」
import java.awt.EventQueue; 
import java.awt.Graphics; 
import java.awt.Graphics2D; 
import java.awt.GridBagLayout; 
import java.awt.event.ActionEvent; 
import java.awt.event.ActionListener; 
import java.util.logging.Level; 
import java.util.logging.Logger; 
import javax.swing.JButton; 
import javax.swing.JFrame; 
import javax.swing.JPanel; 
import javax.swing.UIManager; 
import javax.swing.UnsupportedLookAndFeelException; 

public class Test { 

    public static void main(String[] args) { 
     new Test(); 
    } 

    public Test() { 
     EventQueue.invokeLater(new Runnable() { 
      @Override 
      public void run() { 
       try { 
        UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); 
       } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) { 
        ex.printStackTrace(); 
       } 

       Thread t = new Thread(new Runner()); 
       t.start(); 

       JFrame frame = new JFrame("Testing"); 
       frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
       frame.add(new TestPane()); 
       frame.pack(); 
       frame.setLocationRelativeTo(null); 
       frame.setVisible(true); 
      } 
     }); 
    } 

    public static final Object LOCK = new Object(); 

    public class TestPane extends JPanel { 

     public TestPane() { 
      setLayout(new GridBagLayout()); 
      JButton btn = new JButton("Press me"); 
      btn.addActionListener(new ActionListener() { 
       @Override 
       public void actionPerformed(ActionEvent e) { 
        synchronized (LOCK) { 
         LOCK.notifyAll(); 
        } 
       } 
      }); 
      add(btn); 
     } 

    } 

    public class Runner implements Runnable { 

     @Override 
     public void run() { 
      while (true && !Thread.currentThread().isInterrupted()) { 
       synchronized (LOCK) { 
        try { 
         System.out.println("Nothing to see here, just waiting"); 
         LOCK.wait(); 
        } catch (InterruptedException ex) { 
        } 
       } 
       System.out.println("Look at me, I'm busy"); 
      } 
     } 

    } 
} 

のブロックは任意のアクションを実行し、スイングがシングルスレッドで、決して忘れないでくださいしない、までThreadが動作し続けることができ、それが押されているロックを「通知します」 Event Dispatching Threadのコンテキスト内でブロックしていますが、EDTの外部からUIを更新することは決してありません。

何らかの理由でUIを更新する必要がある場合は、SwingWorkerをご覧になることをお勧めします。これはあなたの人生をはるかに簡単にします。詳細は、Worker Threads and SwingWorkerを参照してください。

ボタンがアクティブになったときに通知されるActionListenerがあります。関連するアクションを実行するためにモニタロックが必要なのはなぜですか?必要な行動を開始するにはかなりの時間がかかりますか?ボタンをクリックするだけで新しいスレッドを開始することができます。

あなたはタイムアウトのいくつかの種類を待っている場合は、その、正直に言うと、スイングTimerはおそらくタスク

+0

ありがとう!必要な行動を開始するのに多くの時間を要します。 –

関連する問題