我正在研究这个应用程序。它实际上是一个语音控制的东西...我发出语音命令并执行了一些动作。但事实是,一旦它被部署,它就在无限循环中,它不断搜索声音(它应该......想象一下铁人电影的jarvis)..但是这个循环冻结了我的gui.I无法更新它。不能隐藏面板,不能播放声音。
摇摆工作者并摇摆 utilitie s不应该帮助我,因为他们在一段时间后检查代码,而我需要实时语音识别..
那么可以做些什么呢?我可以让我的gui与另一个java程序交互吗?像java编程一样会进行语音识别并将回复传递给gui?
这是代码草图
class{
main(){
new class()
}
class(){
frames + content pane initialized
mousePresssed()
{
///the while loop starts here and looks for voice commands..any gui update code doesnt work here..while it detects the voice fine..continuously.
}
}
答案 0 :(得分:2)
基本上,你需要让你的无限循环运行在另一个线程而不是EDT。每当您想要更新GUI时,请使用SwingUtilities.invokeLater
调用在EDT上进行更新。在invokeLater
中调用GUI更新的延迟几乎不会引起注意。 SwingUtilities.invokeLater
不是基于轮询机制。它唯一能做的就是将Runnable
转换为一个事件,然后在EDT上发布。然后,EDT将尽快执行您的Runnable
,大部分时间都会立即执行。
现在有关如何在Thread和GUI之间进行通信的模式,您可以简单地使用“Observer”模式。您的语音识别线程在某种程度上是一个模型,您的UI只是监听该模型的变化。每当模型发生变化时,UI都会自行更新。
我做了一个虚构的例子。对于“观察者”模式,我使用了PropertyChangeSupport
。
对于模型,我创建了一个虚拟线程,每隔一段时间就生成一个随机的“命令”,UI会相应地更新自己:
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.beans.PropertyChangeSupport;
import java.util.Random;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.SwingUtilities;
public class TestThreadingAndGUI implements PropertyChangeListener {
private JFrame frame;
private JLabel label;
private DummyRunnable runnable;
public static class DummyRunnable implements Runnable {
private PropertyChangeSupport pcs = new PropertyChangeSupport(this);
private String command;
public void addPropertyChangeListener(PropertyChangeListener listener) {
pcs.addPropertyChangeListener(listener);
}
@Override
public void run() {
Random random = new Random();
while (true) {
try {
Thread.sleep(((random.nextInt(3)) + 1) * 1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
StringBuilder sb = new StringBuilder();
for (int i = 0; i < 15; i++) {
sb.append((char) ('a' + random.nextInt(26)));
}
setCommand(sb.toString());
}
}
public String getCommand() {
return command;
}
private void setCommand(String command) {
String old = this.command;
this.command = command;
pcs.firePropertyChange("command", old, command);
}
}
protected void initUI(DummyRunnable runnable) {
frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
label = new JLabel();
label.setHorizontalAlignment(JLabel.CENTER);
frame.add(label);
frame.setSize(600, 600);
frame.setVisible(true);
this.runnable = runnable;
runnable.addPropertyChangeListener(this);
}
private void executeCommand() {
label.setText(runnable.getCommand());
}
@Override
public void propertyChange(PropertyChangeEvent evt) {
if (evt.getPropertyName().equals("command")) {
// Received new command (outside EDT)
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
// Updating GUI inside EDT
executeCommand();
}
});
}
}
public static void main(String[] args) {
final DummyRunnable runnable = new DummyRunnable();
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
TestThreadingAndGUI testThreadingAndGUI = new TestThreadingAndGUI();
testThreadingAndGUI.initUI(runnable);
}
});
new Thread(runnable).start();
}
}