Java 使用线程实时更新JTextArea
我试图随机生成一个字符串并不断更新JTextArea。我知道程序在无限循环的runTest()方法中挂起。我试图循环并显示这个结果,直到用户点击停止按钮。有什么建议吗?谢谢Java 使用线程实时更新JTextArea,java,multithreading,swing,jtextarea,Java,Multithreading,Swing,Jtextarea,我试图随机生成一个字符串并不断更新JTextArea。我知道程序在无限循环的runTest()方法中挂起。我试图循环并显示这个结果,直到用户点击停止按钮。有什么建议吗?谢谢 import javax.swing.JButton; import javax.swing.JFrame; import javax.swing.JLabel; import javax.swing.JTextArea; import javax.swing.SwingUtiliti
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JTextArea;
import javax.swing.SwingUtilities;
import java.awt.BorderLayout;
import java.awt.Panel;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Random;
public class MyApplication extends JFrame {
private JTextArea textArea;
private JButton b;
private String toChange = "";
// Called from non-UI thread
private void runQueries() {
while (true) {
runTest();
updateProgress();
}
}
public void runTest() {
while (true) {
if (toChange.length() > 10) {
toChange = "";
}
Random rand = new Random();
toChange += rand.nextInt(10);
}
}
private void updateProgress() {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
textArea.append(toChange);
}
});
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
MyApplication app = new MyApplication();
app.setVisible(true);
}
});
}
private MyApplication() {
this.setLayout(null);
this.setResizable(false);
this.setLocation(100, 100);
this.setSize(900, 600);
final Panel controlPanel = new Panel();
controlPanel.setLayout(new BorderLayout());
controlPanel.setSize(600, 200);
controlPanel.setLocation(50, 50);
setDefaultCloseOperation(this.EXIT_ON_CLOSE);
textArea = new JTextArea("test");
textArea.setSize(100, 100);
textArea.setLocation(200, 200);
this.add(textArea);
JButton b = new JButton("Run query");
b.setSize(100, 75);
b.setLocation(100, 50);
this.add(b);
b.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
Thread queryThread = new Thread() {
public void run() {
runQueries();
}
};
queryThread.start();
}
});
}
}
你会想要像我刚才做的那样的东西。否则,您只需冻结线程,因此,updateProgress()代码>从未被调用
请注意,为什么在runTest()
方法中甚至需要while(true)
循环?runquerys()
中的while-true循环始终在运行和更新它,这意味着while(true)
循环似乎没有任何意义
澄清:
我是说你应该把runTest()和updateProgress()放在一个延迟的任务中,而不是一个while-true循环——否则,你只是把它们放在同一个线程中而耽误了另一个任务
但是,更改此选项也可以解决此问题:
b.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
int initialDelay = 100; // start after 0.1 seconds
int period = 100; // repeat every 0.1 seconds
{
Timer timer = new Timer();
TimerTask task = new TimerTask() {
public void run() {
runTest();
};
timer.scheduleAtFixedRate(task, initialDelay, period);
}
{
Timer timer = new Timer();
TimerTask task = new TimerTask() {
public void run() {
updateProgress();
};
timer.scheduleAtFixedRate(task, initialDelay, period);
}
}
});
}
和runTest()
和updateProgress()
注意,我是在SO编辑器中输入代码,而不是在IDE中。很抱歉出现语法错误
你会想要像我刚才做的那样的东西。否则,您只需冻结线程,因此,updateProgress()代码>从未被调用
请注意,为什么在runTest()
方法中甚至需要while(true)
循环?runquerys()
中的while-true循环始终在运行和更新它,这意味着while(true)
循环似乎没有任何意义
澄清:
我是说你应该把runTest()和updateProgress()放在一个延迟的任务中,而不是一个while-true循环——否则,你只是把它们放在同一个线程中而耽误了另一个任务
但是,更改此选项也可以解决此问题:
b.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
int initialDelay = 100; // start after 0.1 seconds
int period = 100; // repeat every 0.1 seconds
{
Timer timer = new Timer();
TimerTask task = new TimerTask() {
public void run() {
runTest();
};
timer.scheduleAtFixedRate(task, initialDelay, period);
}
{
Timer timer = new Timer();
TimerTask task = new TimerTask() {
public void run() {
updateProgress();
};
timer.scheduleAtFixedRate(task, initialDelay, period);
}
}
});
}
和runTest()
和updateProgress()
注意,我是在SO编辑器中输入代码,而不是在IDE中。很抱歉出现语法错误。请尝试此操作
private void runQueries() {
while (!stop) {
runTest();
updateProgress();
}
}
当您想要完全停止时,makestop
为真,例如点击停止按钮。然后
public void runTest() {
while (true) {
if (toChange.length() > 10) {
toChange = "";
break;
}
Random rand = new Random();
toChange += rand.nextInt(10);
}
}
如果不中断循环,您的updateProgress
将不会调用..试试这个
private void runQueries() {
while (!stop) {
runTest();
updateProgress();
}
}
当您想要完全停止时,makestop
为真,例如点击停止按钮。然后
public void runTest() {
while (true) {
if (toChange.length() > 10) {
toChange = "";
break;
}
Random rand = new Random();
toChange += rand.nextInt(10);
}
}
如果不中断循环,您的updateProgress
将不会调用..最重要的事情之一是,Java中的所有GUI元素都应该在EventDispatchThread上运行,否则可能会导致不可预知的错误行为
请在此阅读:
从您当前的代码可以看出,您正在通过在一个恒定循环中冻结应用程序来对其进行实时锁定
您需要做的是创建一个单独的线程,该线程在创建时会不断更新EDT中的TextArea,但会在主应用程序中引用该线程。
一旦用户按下按钮(这将在EDT上),它应该告诉主线程终止单独的线程,从而停止更新
如果您陷入困境,请随时询问更详细的步骤。我不能强调的最重要的一点是,Java中的所有GUI元素都应该在EventDispatchThread上运行,否则可能会导致不可预知的错误行为
请在此阅读:
从您当前的代码可以看出,您正在通过在一个恒定循环中冻结应用程序来对其进行实时锁定
您需要做的是创建一个单独的线程,该线程在创建时会不断更新EDT中的TextArea,但会在主应用程序中引用该线程。
一旦用户按下按钮(这将在EDT上),它应该告诉主线程终止单独的线程,从而停止更新
如果您陷入困境,请随时询问更详细的步骤。我认为您需要在新线程上重复执行任务。请给我一分钟时间获取代码。将线程queryThread
设为类变量,并在“停止”按钮的actionPerformed()
方法中执行queryThread.interrupt()
。有关更多信息,请参阅。Java GUI必须在不同的操作系统、屏幕大小、屏幕分辨率等上工作。因此,它们不利于像素完美布局。请改为使用布局管理器,或与布局填充和边框一起使用。请参见所示示例。希望如果您阅读了整个主题,您会学到很多关于Swing中并发性的知识。也可以启动和停止,也可以作为SwingWorker的替代品。我想你需要一个新线程上的重复任务。请给我一分钟时间获取代码。将线程queryThread
设为类变量,并在“停止”按钮的actionPerformed()
方法中执行queryThread.interrupt()
。有关更多信息,请参阅。Java GUI必须在不同的操作系统、屏幕大小、屏幕分辨率等上工作。因此,它们不利于像素完美布局。请改为使用布局管理器,或与布局填充和边框一起使用。请参见所示示例。希望如果您阅读了整个主题,您会学到很多关于Swing中并发性的知识。也可以启动和停止,可以作为SwingWorker的替代品。我很难理解这一点,你能用我给出的例子详细说明一下吗?应该在哪里创建计时器?Thanks@JavaNoob我添加了一些澄清,加上一个我之前没有意识到的解决方案。啊,解决方案显示一次,然后冻结程序。@JavaNoob Try now。它应该在不同的线程上不断运行updateProgress()和runTest()。。。这些是正确的进口货吗?导入java.util.TimerTask;导入javax.swing.Timer;我很难理解这一点,你能用我给出的例子详细说明一下吗?该去哪里