2014-10-02 106 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編輯器。

相關問題