2014-10-28 27 views
4

我已經使用JavaFX創建了一個GUI,並且有三個單選按鈕,一旦用戶單擊提交併創建另一個線程,並根據檢查了哪個單選按鈕,線程將運行所需的輸出並將結果輸出到控制檯。如何在JavaFX中排列任務?

但是,當線程正在運行(一個進程需要大約30秒才能完成),我可以檢查任何單選按鈕。爲它創建另一個線程並輸出與另一個正在進行的線程。所以我的輸出盒只是一團亂麻!我正在尋找異步任務,但我不確定這是否與它有關。

以下是我所需要的:如果任務正在運行,並且在運行時單擊提交按鈕,請等待上一個任務結束,然後執行任務。

這裏是我的代碼僞代碼

class TestMain{ 


main class{ 
launch(args); 
} 

declaring a new textfield with name m_status update here 
once submit button is clicked { 


create a new thread to run 



} 
} 


class ThreadBlahBlah implements Runnable{ 

if(first checkbox was selected){ 
//do these fancy stuff 
Platform.runLater(new Runnable() { 
@Override 
    public void run() { 
    TestMain.m_status_update.setText("Test Completed!") ; 


} 
else(second checkbox was selected){ 
//do these other fancy stuff 
Platform.runLater(new Runnable() { 
    @Override 
    public void run() { 
    TestMain.m_status_update.setText("Test Completed!") ; 

} 


} 

請不要推薦我,而正在運行的任務,因爲我想我的排隊等任務鏈表禁用單選按鈕。

回答

5

使用單線程執行程序來運行你的任務:

import java.util.concurrent.ExecutorService; 
import java.util.concurrent.Executors; 
import java.util.concurrent.atomic.AtomicInteger; 

import javafx.application.Application; 
import javafx.beans.binding.Bindings; 
import javafx.beans.property.IntegerProperty; 
import javafx.beans.property.SimpleIntegerProperty; 
import javafx.concurrent.Task; 
import javafx.geometry.Insets; 
import javafx.geometry.Pos; 
import javafx.scene.Scene; 
import javafx.scene.control.Button; 
import javafx.scene.control.Label; 
import javafx.scene.control.TextArea; 
import javafx.scene.layout.BorderPane; 
import javafx.scene.layout.HBox; 
import javafx.stage.Stage; 

public class QueuedTaskExample extends Application { 

    private AtomicInteger taskCount = new AtomicInteger(0); 

    private ExecutorService exec = Executors.newSingleThreadExecutor(r -> { 
     Thread t = new Thread(r); 
     t.setDaemon(true); // allows app to exit if tasks are running 
     return t ; 
    }); 

    // Use the following if you want the tasks to run concurrently, instead of consecutively: 

    // private ExecutorService exec = Executors.newCachedThreadPool(r -> { 
    //  Thread t = new Thread(r); 
    //  t.setDaemon(true); 
    //  return t ; 
    // }); 


    @Override 
    public void start(Stage primaryStage) { 

     // Just keep track of number of tasks pending/running for a status label: 
     IntegerProperty pendingTasks = new SimpleIntegerProperty(0); 

     Button startButton = new Button("Start"); 
     TextArea textArea = new TextArea(); 
     textArea.setEditable(true); 
     startButton.setOnAction(event -> { 
      Task<Void> task = createTask(); 
      // add text to text area if task's message changes: 
      task.messageProperty().addListener((obs, oldMessage, newMessage) -> { 
       textArea.appendText(newMessage); 
       textArea.appendText("\n"); 
      }); 

      // for maintaining status label: 
      pendingTasks.set(pendingTasks.get()+1); 
      task.setOnSucceeded(taskEvent -> pendingTasks.set(pendingTasks.get()-1)); 

      // run task in single-thread executor (will queue if another task is running): 
      exec.submit(task); 
     }); 

     // layout etc 
     HBox controls = new HBox(startButton); 
     controls.setAlignment(Pos.CENTER); 
     controls.setPadding(new Insets(10)); 

     Label statusLabel = new Label(); 
     statusLabel.textProperty().bind(Bindings.format("Pending/running tasks: %s", pendingTasks)); 

     BorderPane root = new BorderPane(textArea, statusLabel, null, controls, null); 
     Scene scene = new Scene(root, 600, 400); 
     primaryStage.setScene(scene); 
     primaryStage.show(); 
    } 

    @Override 
    public void stop() { 
     exec.shutdownNow(); 
    } 

    // Trivial task that counts slowly to 5, updating its message as it goes: 
    private Task<Void> createTask() { 
     final int taskNumber = taskCount.incrementAndGet(); 
     return new Task<Void>() { 
      @Override 
      public Void call() throws Exception { 
       for (int count=1; count<=5; count++) { 
        Thread.sleep(1000); 
        updateMessage("Task "+taskNumber+": Count "+count); 
       } 
       return null ; 
      } 
     }; 
    } 

    public static void main(String[] args) { 
     launch(args); 
    } 
} 
0

當用戶單擊一個單選按鈕時,首先禁用所有單選按鈕,以便用戶在任務運行時無法單擊其他單選按鈕。

完成後臺作業後,重新啓用所有單選按鈕,以便用戶可以選擇其他任務。

參見Node.setDisabled()RadioButton延伸Node)。

如果您確實需要對任務進行排隊,後臺線程應該維護一個任務列表,並且當用戶單擊時,將該任務添加到後臺線程應該使用的列表中(如果當前任務已完成,則開始另一個任務還有更多)。

對於高級線程執行,請參閱ExecutorsExecutorService

+0

但是,如果我很好的用戶在任務運行時選擇的單選按鈕的東西。一旦上一次完成,任務應該開始。有點像排隊!就像鏈接列表 – Indigo 2014-10-28 14:47:07

+0

@OctavianRox然後你應該在你的後臺線程中維護一個任務列表,當用戶點擊時,將任務添加到後臺線程應該使用的列表中(如果當前任務完成並且在那裏開始另一個任務更多)。 – icza 2014-10-28 14:49:55