我希望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:
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 :(得分:5)
如果在Swing事件线程上调用Thread.sleep
,则会将整个应用程序置于睡眠状态,使其无效,但更重要的是,不需要执行此操作。您只需让ActionListener激活需要激活的对象,因为这是事件驱动编程的工作方式。
如果您需要延迟Swing应用程序,请使用Swing Timer,这是本网站上反复讨论的内容。
答案 1 :(得分:2)
这是与线程锁主题相关联的线程等待/通知的基本概念。基本上,你有一些共同的对象,它充当“锁”,一个线程在这个线程上“等待”,当另一个线程需要时,它“通知”监视器已经发生了一些他们应该/可以响应的动作。
首先查看Lock Objects了解更多详情。
以下是该概念的一个非常基本的示例,允许ActionListener
连续运行,但在公共锁上“等待”。按下的Thread
会在按下时“通知”锁定,允许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");
}
}
}
}
继续工作,直到再次阻止“等待”
SwingWorker
请记住,Swing是单线程的,从不执行在事件调度线程的上下文中阻塞的任何操作,同样,永远不要从EDT外部更新UI。
如果您需要从其他线程出于某种原因更新UI,那么我建议您查看ActionListener
,这将使您的生活更加简单。有关详细信息,请参阅Worker Threads and SwingWorker。
您有一个Timer
,当按钮被激活时会通知您,为什么您需要一个监视器锁来执行相关操作?是否需要花费大量时间才能启动所需的操作?您可以在单击按钮时启动新线程。
如果你正在等待某种超时,那么,说实话,Swing {{1}}可能更适合这项任务