使用线程循环更新JFrame [英] Using a thread loop to update a JFrame

查看:136
本文介绍了使用线程循环更新JFrame的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我对在循环中使用线程进行了广泛的搜索,虽然我理解了线程是如何工作的这一概念,但我仍然似乎无法掌握如何在我的简单应用程序中实现它.

我的应用程序由带有文本框的表单组成.一旦循环迭代,则需要更新此文本框.它从按下一个按钮开始,但是循环也应该从按下一个停止按钮结束. Ive使用布尔值来跟踪是否按下了该值.

这是我的表单代码:

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);
    }  
}

如您所见,循环是在单独的线程上创建的...但是文本框仅在循环完成后才更新.现在,据我在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);

    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);
        }
} }

解决方案

为使Tassos的答案生效,您实际上必须创建一个新线程,而您没有这样做.只需致电

 ThreadTester example = new ThreadTester(2,this);
example.run();
 

还不够,只是从EDT调用run方法.您需要执行以下操作:

 Thread t = new Thread(new ThreadTester(2,this));
t.start();
 

请参考定义和启动线程. /p>

此外,您还希望从两个不同的线程(runnable)修改同一字段,这是一个错误.您应该阅读有关Java并发的更多信息.

ive done some extensive searching on using threads in a loop and whilst I understand the concept how how seperate threads work, I still cant seem to grasp how to implement it in my simple application.

My application consists of a form with a text box. This textbox needs to be updated once ever iteration of a loop. It starts with the press of a button but the loop should also finish with the press of a stop button. Ive used a boolean value to track if its been pressed.

Here is my form code:

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);
    }

}

As you can see I have a button that is pressed. When the button is pressed this executes the code thats in a different class called ThreadTester. Here is the code for that class:

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);
    }  
}

as you can see the loop has been created on a seperate thread... but the textbox only updates after the loop has finished. Now as far as im aware in my MainForm I created a seperate thread to run the loop on, so I dont understand why its not running? Any guidence would be much appreciated, ive tried looking at examples on stack exchange but I cant seem to get them to fit into my implemntation.

With the recommendation suggested by Tassos my run method now looks like this:

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);
        }
} }

解决方案

In order for Tassos' answer to work, you actually have to create an new thread, which you did not do. Simply calling

ThreadTester example = new ThreadTester(2,this);
example.run();

is not enough, sice that just calls the run method from EDT. You need to do the following:

Thread t = new Thread(new ThreadTester(2,this));
t.start();

Please refer to Defining and Starting a Thread.

Also, you want modify the same field from two different threads (runnable), which is a bug. You should read more about java concurrency.

这篇关于使用线程循环更新JFrame的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆