2017-01-31 38 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; 
}