将参数传递给父

时间:2017-03-30 13:41:31

标签: java javafx runnable java-threads

我50%绝望:P。我尝试(在开始时)从Thread的代码更新GUI,并获得NullException。阅读了一段时间后,我明白Thread淹没了JavaFX应用程序窗口,为了让我从Thread更新GUI,我需要使用以下代码:

Platform.runLater(new Runnable() {
            @Override public void run() {

            //Update UI here     
            for (int i=0; i<2000;i++)
                {
                 MyMainClass.leftPaneTextArea.appendText("Goodi!\n");
                }

            }
        });

所以我确实使用了这段代码,它确实允许我编辑我的主类的GUI。但是,我的问题很简单。 =&GT;我从一个线程运行的这段代码是一个代码,它位于一个公共void run()(我运行代码的线程)中。它看起来像这样:

@Override
    public void run() {

    String tmpVar;

    ... (Some code)
    ... (Some code)
    ... (Some code)

        Platform.runLater(new Runnable() {
            @Override public void run() {

            //Update UI here     
            for (int i=0; i<2000;i++)
                {
                 MyMainClass.leftPaneTextArea.appendText("Goodi!\n");
                }

            }
        });

    ... (Some code)
    ... (Some code)
    ... (Some code)
}

如何将父公共void run()中的参数传递给这个参数? 例如,String tmpString(我想传递它)。

请注意,如果我在public void run()之外将其声明为静态(例如)=&gt;我运行了很多线程,所以更新静态var可能并不总是准确的(因为很多线程会同时更新它)

谢谢!。

4 个答案:

答案 0 :(得分:4)

基本上,您需要考虑将参数传递给 Runnable 对象,而不是run()方法。

如果你让匿名类成为一个内部类,那就很清楚了:

@Override
public void run() {

    String tmpVar;

    // ... (Some code)
    // ... (Some code)
    // ... (Some code)

        Platform.runLater(new Updater(tmpVar));

    // ... (Some code)
    // ... (Some code)
    // ... (Some code)
}

// ...

public static class Updater implements Runnable {

    private final String var ;

    public Updater(String var) {
        this.var = var ;
    }



    @Override 
    public void run() {

        // Access var here

        for (int i=0; i<2000;i++){
            MyMainClass.leftPaneTextArea.appendText("Goodi!\n");
        }

    }
}

现在,如果tmpVarfinal,或者#34;实际上是 1 &#34;,那么它将适用于您的匿名内部类,并且基本上翻译成与上面的内部类完全相同的东西(换句话说,匿名内部类获得一个隐含的字段,其中填充了最终变量的值):

@Override
public void run() {

    final String tmpVar = ...;

    // ... (Some code)
    // ... (Some code)
    // ... (Some code)

    Platform.runLater(new Runnable() {
        @Override public void run() {

        // access tmpVar here:

        for (int i=0; i<2000;i++)
            {
             MyMainClass.leftPaneTextArea.appendText("Goodi!\n");
            }

        }
    });

    // ... (Some code)
    // ... (Some code)
    // ... (Some code)
}

语言设计者可以实际上使用非最终变量进行此工作,但决定结果会太混乱。会发生什么会被翻译成上面看到的同一个内部类:换句话说,tmpVar当前值将被隐式传递给匿名内部的一个字段类。这将是一个全新的变量,具有与您正在访问的范围不同的范围,其值将是&#34;快照&#34;创建匿名内部类时tmpVar的值。看似是一个实际上引用两个不同变量的变量可能具有不同的值被认为过于混乱且容易出错。

但是,如果tmpVar不是最终的(或有效的最终):即您要多次分配值,您可以显式&#34;快照&#34;变量的值:

@Override
public void run() {

    String tmpVar ;

    // ... (Some code)
    // ... (Some code)
    // ... (Some code)

    final String varCopy = tmpVar ;

    Platform.runLater(new Runnable() {
        @Override public void run() {

        // access varCopy here:

        for (int i=0; i<2000;i++)
            {
             MyMainClass.leftPaneTextArea.appendText("Goodi!\n");
            }

        }
    });

    // ... (Some code)
    // ... (Some code)
    // ... (Some code)
}

(1)&#34;有效决赛&#34;表示为变量分配值恰好一次。等效地,它意味着您可以声明它final而不会产生任何编译错误。

答案 1 :(得分:0)

James_D发布的一个选项是在内部类中使用final var(匿名与否)

new MyRunnable(someString)或使用Consumer<T>等Anoter选项,您可以找到here

答案 2 :(得分:0)

你总是可以使用吸气剂......

public class YourClass {
    private String myVar;

    public void do something(String aVal) {
        myVar= "Value you want to pass";

        this.runOnUiThread(new Runnable() {
            @Override
            public void run() {    
                Log.d("TAG",getMyVar());
            }
        });
    }

    private String myVar(){
        return myVar;
    }
}

答案 3 :(得分:-1)

您要做的是反对重写规则。 如果您要在run()方法中传递任何参数,那么实际上您正在重载run()方法,并且无论如何都不会调用它 创建新线程时,no-arg run()方法就是名为。

的方法

我建议将信息存储在static上下文中的其他位置,然后使用run()方法检索它。