2014-10-02 56 views
0

如何在JavaFX中使用FXML和任务或服务类中的线程?如何在JavaFX中使用并发(线程)(使用FXML !!!(JavaFX Scene Builder))?

我需要并发程序,因为我使用了一个非常长的循环。 如果我使用“手动”(无FXML)编码,那么它就可以工作。但使用FXML它不起作用(JavaFX Scene Builder)。而不是打印出控制台中的“字符串缓冲区”变量,我想将它写入textarea(这是一个可更新的组件)。但是在这种情况下,当然会出现错误消息,因为它不再属于JavaFX应用程序线程。我如何使这个组件(TextArea textAreaAusgabe)更新/更新,以便我可以在线程中使用它? 对不起我的英文不好? 希望你知道我的问题是什么(它是FXML:-D)。 如果在NetBeans中有另一个gui构建器,我将使用它构建swing的gui构建器。 据我所知道的是场景生成器我想在我的代码片段使用TASK3为JavaFX独一无二的GUI构建:-(。

。 这里是我的代码片段不工作(如果我使用如标签,文本框等)成分:

import java.net.URL; 
import java.util.ResourceBundle; 
import javafx.fxml.Initializable; 
import javafx.scene.control.Button; 
import javafx.scene.control.TextArea; 
import java.io.*; 
import java.util.Random; 
import java.util.Arrays; 
import javafx.application.Platform; 
import javafx.concurrent.Service; 
import javafx.concurrent.Task; 
import javafx.event.ActionEvent; 
import javafx.fxml.FXML; 
import javafx.scene.control.CheckBox; 
import javafx.scene.control.Label; 
import javafx.scene.control.ProgressBar; 
import javafx.scene.control.ProgressIndicator; 
import javax.swing.JOptionPane; 
import javax.swing.filechooser.FileSystemView; 
public class Kontroller implements Initializable 
{ 

    int array [ ] = new int [50]; 
    int counter = 0; 

    String buffer; 

    int z; 

    public TextArea textAreaAusgabe; 
    public Button buttonBerechnen; 
    public Button buttonReset; 
    public Label labelAnzahl; 
    public ProgressBar progressBar; 
    public ProgressIndicator progressIndikator; 

    public CheckBox checkBox1; 
    public CheckBox checkBox2; 
    public CheckBox checkBox3; 
    public CheckBox checkBox4; 
    public CheckBox checkBox5; 
    public CheckBox checkBox6; 
    public CheckBox checkBox7; 
    public CheckBox checkBox8; 
    public CheckBox checkBox9; 
    public CheckBox checkBox10; 

    Task <Integer> task = new Task <Integer> () 
    { 
     @Override 
     protected Integer call () throws Exception 
     { 
      int i; 
      for (i = 0; i < 100; i++) 
      { 
       if (isCancelled ()) 
       { 
        break; 
       } 
       System.out.println("Anzahl " + i); 
      } 
      return i; 
     } 
    }; 

    Task <Integer> task2 = new Task <Integer> () 
    { 
     @Override 
     protected Integer call () throws Exception 
     { 
      int j; 
      for (j = 0; j < 1000; j++) 
      { 
       if (isCancelled ()) 
       { 
        updateMessage ("Abgebrochen"); 
        break; 
       } 
       System.out.println ("Anzahl " + j); 
       updateMessage ("Anzahl " + j); 
       updateProgress (j, 1000); 
       try 
       { 
        Thread.sleep (1); 
       } catch (InterruptedException interrupted) 
       { 
        if (isCancelled ()) 
        { 
         updateMessage ("Abgebrochen"); 
         break; 
        } 
       } 
      } 
      return j; 
     } 
    }; 

    Service <Void> service = new Service <Void> () 
    { 
     @Override 
     protected Task <Void> createTask () 
     { 
      return new Task <Void> () 
      { 
       @Override 
       protected Void call () throws Exception 
       { 
        return null; 
       } 
      }; 
     } 
     @Override 
     protected void succeeded () 
     { 

     } 
    }; 

    Task task3 = new Task <Void> () 
    { 
     @Override public Void call () throws IOException 
     { 
      File ergebnis = new File (FileSystemView.getFileSystemView ().getHomeDirectory ().getAbsolutePath () + "\\Ergebnis.txt"); 
      final FileWriter fw = new FileWriter (ergebnis); 

      for (int k = 1; k <= 10000000; k++) 
      { 
       if (isCancelled ()) 
       { 
        break; 
       } 
       updateProgress (k, 10000000); 
       Arrays.fill (array, 0); 

      // textAreaAusgabe.appendText (buffer); // Does not work 
      System.out.println (buffer); // Works 
      System.out.println (counter++); 
      System.out.println (); 
      fw.append (System.getProperty ("line.separator")); 
      fw.append (System.getProperty ("line.separator")); 
      fw.append (""+counter+""); 
      fw.append (System.getProperty ("line.separator")); 
      fw.append (System.getProperty ("line.separator")); 

      } 
      return null; 
     } 
    }; 

    Thread thread = new Thread (task3); 

    public void reset () 
    { 
     // Zurücksetzen 
    } 
    public void berechnen (ActionEvent event) 
    { 
     thread.setDaemon (true); 
     thread.start (); 
    } 
    public void fehler () 
    { 
     // Zeige Stage bei Fehler 
    } 
    public void initialize (URL url, ResourceBundle rb) 
    { 
     progressBar.progressProperty ().bind (task3.progressProperty ()); 
     progressIndikator.progressProperty ().bind (task3.progressProperty ()); 
    } 
} 

如果我注释掉行:

// textAreaAusgabe.appendText (buffer); // Does not work 

出现以下错误:

Exception in thread "Thread-4" java.lang.IllegalStateException: Not on FX application thread; currentThread = Thread-4 

而且这是在NetBeans输出完整的错误消息:

ant -f D:\\Users\\Benutzer\\Documents\\NetBeansProjects\\Threading jfxsa-run 
init: 
Deleting: D:\Users\Benutzer\Documents\NetBeansProjects\Threading\build\built-jar.properties 
deps-jar: 
Updating property file: D:\Users\Benutzer\Documents\NetBeansProjects\Threading\build\built-jar.properties 
Compiling 1 source file to D:\Users\Benutzer\Documents\NetBeansProjects\Threading\build\classes 
warning: [options] bootstrap class path not set in conjunction with -source 1.5 
warning: [options] source value 1.5 is obsolete and will be removed in a future release 
warning: [options] target value 1.5 is obsolete and will be removed in a future release 
warning: [options] To suppress warnings about obsolete options, use -Xlint:-options. 
4 warnings 
compile: 
Detected JavaFX Ant API version 1.3 
Launching <fx:jar> task from F:\Java\Java Development Kit\Java Development Kit (1.8.0_20) (x64)\jre\..\lib\ant-javafx.jar 
Warning: From JDK7u25 the Codebase manifest attribute should be used to restrict JAR repurposing. 
     Please set manifest.custom.codebase property to override the current default non-secure value '*'. 
Launching <fx:deploy> task from F:\Java\Java Development Kit\Java Development Kit (1.8.0_20) (x64)\jre\..\lib\ant-javafx.jar 
jfx-deployment-script: 
jfx-deployment: 
jar: 
Copying 12 files to D:\Users\Benutzer\Documents\NetBeansProjects\Threading\dist\run1389427067 
jfx-project-run: 
Executing D:\Users\Benutzer\Documents\NetBeansProjects\Threading\dist\run1389427067\Threading.jar using platform F:\Java\Java Development Kit\Java Development Kit (1.8.0_20) (x64)\jre/bin/java 
Exception in thread "Thread-4" java.lang.IllegalStateException: Not on FX application thread; currentThread = Thread-4 
    at com.sun.javafx.tk.Toolkit.checkFxUserThread(Toolkit.java:204) 
    at com.sun.javafx.tk.quantum.QuantumToolkit.checkFxUserThread(QuantumToolkit.java:364) 
    at javafx.scene.Scene.addToDirtyList(Scene.java:485) 
    at javafx.scene.Node.addToSceneDirtyList(Node.java:424) 
    at javafx.scene.Node.impl_markDirty(Node.java:415) 
    at javafx.scene.shape.Shape.impl_markDirty(Shape.java:942) 
    at javafx.scene.Node.impl_geomChanged(Node.java:3784) 
    at javafx.scene.text.Text.impl_geomChanged(Text.java:763) 
    at javafx.scene.text.Text.needsTextLayout(Text.java:194) 
    at javafx.scene.text.Text.needsFullTextLayout(Text.java:189) 
    at javafx.scene.text.Text.access$200(Text.java:96) 
    at javafx.scene.text.Text$2.invalidated(Text.java:386) 
    at javafx.beans.property.StringPropertyBase.markInvalid(StringPropertyBase.java:109) 
    at javafx.beans.property.StringPropertyBase.set(StringPropertyBase.java:143) 
    at javafx.beans.property.StringPropertyBase.set(StringPropertyBase.java:49) 
    at javafx.scene.text.Text.setText(Text.java:367) 
    at com.sun.javafx.scene.control.skin.TextAreaSkin.lambda$new$231(TextAreaSkin.java:571) 
    at com.sun.javafx.scene.control.skin.TextAreaSkin$$Lambda$256/235779996.invalidated(Unknown Source) 
    at com.sun.javafx.binding.ExpressionHelper$Generic.fireValueChangedEvent(ExpressionHelper.java:349) 
    at com.sun.javafx.binding.ExpressionHelper.fireValueChangedEvent(ExpressionHelper.java:81) 
    at javafx.scene.control.TextInputControl$TextProperty.fireValueChangedEvent(TextInputControl.java:1123) 
    at javafx.scene.control.TextInputControl$TextProperty.markInvalid(TextInputControl.java:1127) 
    at javafx.scene.control.TextInputControl$TextProperty.invalidate(TextInputControl.java:1066) 
    at javafx.scene.control.TextInputControl$TextProperty.access$1300(TextInputControl.java:1038) 

回答

2

您的问题没有具体FXML。

您的问题是您的任务代码违反了JavaFX线程规则(即,您无法修改活动场景中的JavaFX应用程序线程以外的节点)。

更换不工作的代码:

textAreaAusgabe.appendText (buffer); // Does not work 

有了:

Platform.runLater(() -> textAreaAusgabe.appendText (buffer)); 

这将执行JavaFX应用程序线程上的文本区域节点的操作和解决你的线程运行的问题。

请参阅Task文档部分“修改场景图的任务”。

但是,在您的示例应用程序中,现在您将遇到另一个问题,因为您将快速更新JavaFX场景一亿次,这将使JavaFX系统过载并使您的应用程序无响应。你需要做的是批量修改你的文本,只发布runlater调用来每秒更新UI不超过60次。无论如何,要求UI每秒更新超过60次是没有用的,因为没有人可以看到中间更新。

另外,要回答您的问题=>否,目前没有比SceneBuilder更多的JavaFX GUI编辑器。

相关问题