2017-01-31 24 views
0

我有一個方法從數據庫讀取值並返回Map<Integer,String>.此方法需要一些時間才能返回映射。JavaFX:在進程運行時禁用所有組件,並顯示進度指示器

直到時間值被讀取我想要一個進度指示器(只有加載環像指示器就足夠了,不需要進度條)在屏幕上顯示,所有其他組件應該被禁用,直到時間進度條是所示。

public void scanDevice() { 
    ObservableList<TextField> list = FXCollections.observableArrayList(vehicleId, vehicleName, deviceType, 
      offboardBroker1, offboardBroker2, postfixQueue, pKIServer); 
    editedValuesMap.clear(); 
    // devicePlugged = true; 
    if (cbChooseProject.getSelectionModel().getSelectedItem() != null) { 
     try { 
      devicePlugged = dsAdapter.getAdapter(); 
      if (devicePlugged) { 
       if (bScanDevice.isFocused()) { 
        readMap = new HashMap<Integer, String>(); 
        //Process Start 
        readMap = dsAdapter.initScan(); 
        //Process End 

        if (!readMap.isEmpty() && readMap != null) { 
         isWritten = true; 
         isDeviceSideEnabled(); 
         editDeviceContents.setDisable(false); 
         vehicleId.setText(readMap.get(0)); 
         vehicleName.setText(readMap.get(1)); 
         deviceType.setText(readMap.get(2)); 
         offboardBroker1.setText(readMap.get(3)); 
         offboardBroker2.setText(readMap.get(4)); 
         postfixQueue.setText(readMap.get(5)); 
         pKIServer.setText(readMap.get(6)); 
         lContentsSerialNo.setText(readMap.get(7)); 
        } 
       } 
      } 

回答

0

你可以禁用用的方法等所有節點以下,但如果你也想要同時有事情發生使用StackPane可以彼此疊加等待首選。

public void setNodesDiabled(boolean disable, Node... nodes) { 
    for(Node node : nodes) { 
     node.setDisable(disable); 
    } 
} 

使用任意節點數,您可以禁用和重新啓用與進程相關的儘可能多的節點。它也有助於清理,因爲您不會有幾個node.setDisable(true); node2.setDisable(true);等。

在這個例子中,你將不需要0​​,因爲StackPane疊加層可以防止點擊除了裏面的東西之外的任何東西。背景顏色是70%alpha的灰色,以便您可以告訴它是覆蓋層。

public class ProgressExample extends Application { 

    public StackPane layout, main, progress; 

    public StackPane createProgressPane() { 
     ProgressIndicator indicator = new ProgressIndicator(); 
     indicator.setMaxHeight(50); 
     indicator.setMaxWidth(50); 

     StackPane pane = new StackPane(); 
     pane.setAlignment(Pos.CENTER); 
     pane.setStyle("-fx-background-color: rgba(160,160,160,0.7)"); 
     pane.getChildren().add(indicator); 

     Task<Void> task = new Task<Void>(){ 
      protected Void call() throws Exception { 
       // Your process here. 
       // Any changes to UI components must be inside Platform.runLater() or else it will hang. 
       Thread.sleep(2000); 

       Platform.runLater(() -> { 
        layout.getChildren().remove(pane); 
       }); 
       return null; 
      } 
     }; 
     new Thread(task).start(); 
     return pane; 
    } 

    public StackPane createMainPane() { 
     Label label = new Label("Hello World!"); 
     label.setFont(Font.font("Tahoma", FontWeight.SEMI_BOLD, 16)); 

     Button start = new Button("Start Process"); 
     start.setOnAction(action -> { 
      progress = createProgressPane(); 
      layout.getChildren().add(progress); 
     }); 

     VBox vbox = new VBox(10); 
     vbox.setAlignment(Pos.CENTER); 
     vbox.getChildren().addAll(label, start); 
     vbox.setPadding(new Insets(10,10,10,10)); 

     StackPane pane = new StackPane(); 
     pane.getChildren().add(vbox); 
     return pane; 
    } 

    public void start(Stage stage) throws Exception { 
     main = createMainPane(); 

     layout = new StackPane(); 
     layout.getChildren().add(main); 

     Scene scene = new Scene(layout, 900, 550); 
     stage.setScene(scene); 
     stage.setTitle("Progress Example"); 
     stage.setOnCloseRequest(e -> { 
      Platform.exit(); 
      System.exit(0); 
     }); 
     stage.show(); 
    } 

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

我相信問題是,你正在試圖改變Task內的TextField S中的值是不是FX應用程序線程這就是爲什麼你越來越Not on FX application thread。爲了解決這個問題,你需要把你的行修改爲Platform.runLater()內的節點,如下所示。

if (readMap != null && !readMap.isEmpty()) { // Swap the order, can't check empty if it's null. 
    isWritten = true; 
    isDeviceSideEnabled(); 
    Platform.runLater(() -> { 
     editDeviceContents.setDisable(false); 
     vehicleId.setText(readMap.get(0)); 
     vehicleName.setText(readMap.get(1)); 
     deviceType.setText(readMap.get(2)); 
     offboardBroker1.setText(readMap.get(3)); 
     offboardBroker2.setText(readMap.get(4)); 
     postfixQueue.setText(readMap.get(5)); 
     pKIServer.setText(readMap.get(6)); 
     lContentsSerialNo.setText(readMap.get(7)); 
    }); 
} 
+0

你能告訴我這是什麼Thread.sleep(2000); 我是否需要計算我的方法所需的時間,然後在那段時間睡眠該線程,並且由於項目包含我必須使用BorderPane佈局。 我收到以下錯誤: 線程「線程-5」中的異常java.lang.IllegalStateException:不在FX應用程序線程上; currentThread = Thread-5 –

+0

在這個例子中使用'Thread.sleep(2000);'只是因爲它是一個例子。如果沒有任何內容需要花費時間,那麼進度窗格在測試時不會顯示足夠長的時間。你不需要它。至於錯誤,你可以編輯問題在「Task」中包含這些行嗎?你需要在你自己的'Platform.runLater()'中放置改變FX節點和窗格的行。 –

+0

Mathews,我添加了包含我的過程的代碼。該過程從設備a讀取的值顯示在UI上。 –

1

這裏是一個SSCE:

它採用了Service可以多次啓動。它不完整,但開始。

public class Main extends Application { 
    @Override 
    public void start(Stage primaryStage) { 

     BorderPane root = new BorderPane(); 
     Scene scene = new Scene(root, 400, 400); 
     scene.getStylesheets().add(getClass().getResource("application.css").toExternalForm()); 

     Service<Void> serv = new Service<Void>() { 

      @Override 
      protected Task<Void> createTask() { 
       return new Task<Void>() { 

        @Override 
        protected Void call() throws Exception { 
         int maxWork = 10; 
         for (int i = 0; i < maxWork; i++) { 
          Thread.sleep(1000); 
          updateProgress(i + 1, maxWork); 
         } 

         return null; 
        } 

        @Override 
        protected void succeeded() { 
         super.succeeded(); 
         updateProgress(1, 1); 
        } 

        @Override 
        protected void cancelled() { 
         super.cancelled(); 
         updateProgress(1, 1); 
        } 

        @Override 
        protected void failed() { 
         super.failed(); 
         updateProgress(1, 1); 
        } 

       }; 
      } 
     }; 

     ProgressIndicator pi = new ProgressIndicator(); 
     pi.progressProperty().bind(serv.progressProperty()); 


     Button bStart = new Button("Start"); 
     bStart.setOnAction(e -> { 
      serv.reset(); 
      serv.start(); 
     }); 

     root.setCenter(bStart); 
     root.setBottom(pi); 

     primaryStage.setScene(scene); 
     primaryStage.show(); 

     pi.getScene().getRoot().disableProperty().bind(serv.runningProperty()); 
    } 

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

在CSS我說:

.progress-indicator:disabled { 
    -fx-opacity: 1; 
}