Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/355.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 使用线程循环更新JFrame_Java_Multithreading_Swing_Loops_Jframe - Fatal编程技术网

Java 使用线程循环更新JFrame

Java 使用线程循环更新JFrame,java,multithreading,swing,loops,jframe,Java,Multithreading,Swing,Loops,Jframe,我在循环中使用线程方面做了一些广泛的研究,虽然我理解了分离线程如何工作的概念,但我似乎仍然无法掌握如何在我的简单应用程序中实现它 我的应用程序由一个带有文本框的表单组成。此文本框需要在循环的任何迭代中更新一次。它以按下按钮开始,但循环也应以按下停止按钮结束。我用一个布尔值来跟踪它是否被按下 这是我的表格代码: package threadtester; public class MainForm extends javax.swing.JFrame { public MainForm

我在循环中使用线程方面做了一些广泛的研究,虽然我理解了分离线程如何工作的概念,但我似乎仍然无法掌握如何在我的简单应用程序中实现它

我的应用程序由一个带有文本框的表单组成。此文本框需要在循环的任何迭代中更新一次。它以按下按钮开始,但循环也应以按下停止按钮结束。我用一个布尔值来跟踪它是否被按下

这是我的表格代码:

package threadtester;

public class MainForm extends javax.swing.JFrame {

    public MainForm() {
        initComponents();
    }

    private void RunButtonActionPerformed(java.awt.event.ActionEvent evt) {
       ThreadTester.setRunnable(true);
       ThreadTester example = new ThreadTester(2,this);
       example.run();
    }

    private void StopButtonActionPerformed(java.awt.event.ActionEvent evt) {
       ThreadTester.setRunnable(false);
    }


    public static void main(String args[]) {

    java.awt.EventQueue.invokeLater(new Runnable() {
            public void run() {
                new MainForm().setVisible(true);
            }
        });
    }

    public void setTextBox(String myString){
    MainTextbox.setText(myString);
    }

}
正如你所看到的,我有一个按钮被按下了。当按下按钮时,它将执行另一个名为ThreadTester的类中的代码。下面是该类的代码:

package threadtester;

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

public class ThreadTester implements Runnable
{
    int thisThread;
    MainForm myMainForm;
    private static boolean runnable;
    // constructor
    public ThreadTester (int number,MainForm mainForm)
    {
        thisThread = number;
        myMainForm = mainForm;   
    }

    public void run ()
    {
    for (int i =0;i< 20; i++) {
        if(runnable==false){
           break;
        } 
        System.out.println("I'm in thread " + thisThread + " line " + i);
        myMainForm.setTextBox(i + "counter");
        try {
               Thread.sleep(1000);
        } catch (InterruptedException ex) {
            Logger.getLogger(ThreadTester.class.getName()).log(Level.SEVERE, null, ex);
        }
    } }

    public static void setRunnable(Boolean myValue){
       runnable = myValue;
    }

    public static void main(String[] args) {

        MainForm.main(args);
    }  
}
package螺纹测试仪;
导入java.util.logging.Level;
导入java.util.logging.Logger;
公共类ThreadTester实现可运行
{
int这个线程;
MainForm我的MainForm;
私有静态布尔可运行;
//建造师
公共螺纹测试仪(国际编号,主表格主表格)
{
此线程=编号;
myMainForm=mainForm;
}
公开作废运行()
{
对于(int i=0;i<20;i++){
if(runnable==false){
打破
} 
System.out.println(“我在线程中”+这个线程+“行”+I);
myMainForm.setTextBox(i+“计数器”);
试一试{
睡眠(1000);
}捕获(中断异常例外){
Logger.getLogger(ThreadTester.class.getName()).log(Level.SEVERE,null,ex);
}
} }
公共静态void setRunnable(布尔myValue){
runnable=myValue;
}
公共静态void main(字符串[]args){
MainForm.main(args);
}  
}
正如您所看到的,循环是在一个单独的线程上创建的。。。但文本框仅在循环完成后更新。现在据我所知,在我的主窗体中,我创建了一个单独的线程来运行循环,所以我不明白为什么它不运行?任何指导都将不胜感激,我曾尝试查看堆栈交换上的示例,但我似乎无法使它们适合我的实现

根据Tassos的建议,我的跑步方法现在如下所示:

public void run ()
{
for (int i =0;i< 20; i++) {
    if(runnable==false){
        break;
    }
    System.out.println("I'm in thread " + thisThread + " line " + i);

    final String var = i + "counter";
        java.awt.EventQueue.invokeLater(new Runnable() {
        public void run() {
                myMainForm.setTextBox(var);
        }
    });


    try {
            Thread.sleep(1000);
        } catch (InterruptedException ex) {
            Logger.getLogger(ThreadTester.class.getName()).log(Level.SEVERE, null, ex);
        }
} }
公共作废运行()
{
对于(int i=0;i<20;i++){
if(runnable==false){
打破
}
System.out.println(“我在线程中”+这个线程+“行”+I);
最终字符串var=i+“计数器”;
invokeLater(new Runnable()){
公开募捐{
myMainForm.setTextBox(var);
}
});
试一试{
睡眠(1000);
}捕获(中断异常例外){
Logger.getLogger(ThreadTester.class.getName()).log(Level.SEVERE,null,ex);
}
} }
更改此行

    myMainForm.setTextBox(i + "counter");
进入


为什么??因为您无法在非UI线程中执行UI工作。

问题在于您正在阻止EDT(事件调度线程),阻止UI刷新,直到循环完成

这些问题的解决方案总是相同的,使用Swing
定时器或使用SwingWorker

下面是一个使用
SwingWorker
的示例:

import java.awt.BorderLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.List;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JTextField;
import javax.swing.SwingUtilities;
import javax.swing.SwingWorker;

public class TestSwingWorker {

    private JTextField progressTextField;

    protected void initUI() {
        final JFrame frame = new JFrame();
        frame.setTitle(TestSwingWorker.class.getSimpleName());
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        JButton button = new JButton("Clik me to start work");
        button.addActionListener(new ActionListener() {

            @Override
            public void actionPerformed(ActionEvent e) {
                doWork();
            }
        });
        progressTextField = new JTextField(25);
        progressTextField.setEditable(false);
        frame.add(progressTextField, BorderLayout.NORTH);
        frame.add(button, BorderLayout.SOUTH);
        frame.pack();
        frame.setVisible(true);
    }

    protected void doWork() {
        SwingWorker<Void, Integer> worker = new SwingWorker<Void, Integer>() {
            @Override
            protected Void doInBackground() throws Exception {
                // Here not in the EDT
                for (int i = 0; i < 100; i++) {
                    // Simulates work
                    Thread.sleep(10);
                    publish(i); // published values are passed to the #process(List) method
                }
                return null;
            }

            @Override
            protected void process(List<Integer> chunks) {
                // chunks are values retrieved from #publish()
                // Here we are on the EDT and can safely update the UI
                progressTextField.setText(chunks.get(chunks.size() - 1).toString());
            }

            @Override
            protected void done() {
                // Invoked when the SwingWorker has finished
                // We are on the EDT, we can safely update the UI
                progressTextField.setText("Done");
            }
        };
        worker.execute();
    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(new Runnable() {
            @Override
            public void run() {
                new TestSwingWorker().initUI();
            }
        });
    }
}
导入java.awt.BorderLayout;
导入java.awt.event.ActionEvent;
导入java.awt.event.ActionListener;
导入java.util.List;
导入javax.swing.JButton;
导入javax.swing.JFrame;
导入javax.swing.JTextField;
导入javax.swing.SwingUtilities;
导入javax.swing.SwingWorker;
公共类TestSwingWorker{
私有JTextField progressTextField;
受保护的void initUI(){
最终JFrame=新JFrame();
setTitle(TestSwingWorker.class.getSimpleName());
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JButton button=新JButton(“点击我开始工作”);
addActionListener(新建ActionListener()){
@凌驾
已执行的公共无效操作(操作事件e){
销钉();
}
});
progressTextField=新的JTextField(25);
progressTextField.setEditable(false);
frame.add(progressTextField,BorderLayout.NORTH);
框架。添加(按钮,边框布局。南);
frame.pack();
frame.setVisible(true);
}
受保护的空榫(){
SwingWorker worker=新SwingWorker(){
@凌驾
受保护的Void doInBackground()引发异常{
//这里不是EDT
对于(int i=0;i<100;i++){
//模拟工作
睡眠(10);
publish(i);//将已发布的值传递给#process(List)方法
}
返回null;
}
@凌驾
受保护的无效进程(列表块){
//块是从#publish()检索的值
//这里我们在EDT上,可以安全地更新UI
progressTextField.setText(chunks.get(chunks.size()-1.toString());
}
@凌驾
受保护的void done(){
//SwingWorker完成后调用
//我们在EDT上,我们可以安全地更新UI
progressTextField.setText(“完成”);
}
};
worker.execute();
}
公共静态void main(字符串[]args){
SwingUtilities.invokeLater(新的Runnable(){
@凌驾
公开募捐{
新建TestSwingWorker().initUI();
}
});
}
}

为了让Tassos的答案起作用,您实际上必须创建一个新线程,而您没有这样做。简单的呼唤

ThreadTester示例=新的ThreadTester(2,本);
例如,run();
仅从EDT调用
run
方法是不够的。您需要执行以下操作:

Thread t=新螺纹(新螺纹测试仪(2,本));
t、 start();
请参阅
import java.awt.BorderLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.List;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JTextField;
import javax.swing.SwingUtilities;
import javax.swing.SwingWorker;

public class TestSwingWorker {

    private JTextField progressTextField;

    protected void initUI() {
        final JFrame frame = new JFrame();
        frame.setTitle(TestSwingWorker.class.getSimpleName());
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        JButton button = new JButton("Clik me to start work");
        button.addActionListener(new ActionListener() {

            @Override
            public void actionPerformed(ActionEvent e) {
                doWork();
            }
        });
        progressTextField = new JTextField(25);
        progressTextField.setEditable(false);
        frame.add(progressTextField, BorderLayout.NORTH);
        frame.add(button, BorderLayout.SOUTH);
        frame.pack();
        frame.setVisible(true);
    }

    protected void doWork() {
        SwingWorker<Void, Integer> worker = new SwingWorker<Void, Integer>() {
            @Override
            protected Void doInBackground() throws Exception {
                // Here not in the EDT
                for (int i = 0; i < 100; i++) {
                    // Simulates work
                    Thread.sleep(10);
                    publish(i); // published values are passed to the #process(List) method
                }
                return null;
            }

            @Override
            protected void process(List<Integer> chunks) {
                // chunks are values retrieved from #publish()
                // Here we are on the EDT and can safely update the UI
                progressTextField.setText(chunks.get(chunks.size() - 1).toString());
            }

            @Override
            protected void done() {
                // Invoked when the SwingWorker has finished
                // We are on the EDT, we can safely update the UI
                progressTextField.setText("Done");
            }
        };
        worker.execute();
    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(new Runnable() {
            @Override
            public void run() {
                new TestSwingWorker().initUI();
            }
        });
    }
}