I have a static file upload method:

public class Downloader { private static MainLayoutController mlController; private static int doneQuantity = 0; public static void setController(MainLayoutController c) { mlController = c; } public static void downloadFile(String url, String savePath, int buffSize) { try { /* Get connection */ URL connection = new URL(url); HttpURLConnection urlconn; urlconn = (HttpURLConnection) connection.openConnection(); urlconn.setRequestMethod("GET"); urlconn.connect(); /* Set input stream */ InputStream in = null; in = urlconn.getInputStream(); /* Find file full path */ String[] tempArr = url.split("/"); String fullPath = savePath + tempArr[tempArr.length - 1]; /* Set Labels */ //mlController.downloadingLabel.setText(tempArr[tempArr.length - 1]); //mlController.downloadedLabel.setText(doneQuantity + "/" + mlController.quantity); /*Task task = new Task() { @Override protected Integer call() throws Exception { Platform.runLater(() -> updateTitle(tempArr[tempArr.length - 1])); return 101; } }; mlController.downloadingLabel.textProperty().bind(task.titleProperty()); new Thread(task).start();*/ /* Set write stream */ OutputStream writer = new FileOutputStream(fullPath); byte buffer[] = new byte[buffSize]; // Max bytes per one reception /* Download */ int i = 0; double getted_b = 0.0; long delta_t = System.nanoTime(), i_sum = 0; while ((i = in.read(buffer)) > 0) { getted_b += i; i_sum += i; writer.write(buffer, 0, i); if ((System.nanoTime() - delta_t) >= 1E9) { // If the second was over int kb, mb; mb = new Double(getted_b / (1024 * 1024)).intValue(); kb = new Double((getted_b / 1024) % 1024).intValue(); System.out.println(" >> Speed: " + mb + " " + kb + " Mb/sec"); System.out.println(" >> " + i_sum / (urlconn.getContentLength() / 100) + "%"); delta_t = System.nanoTime(); // Set to zero getted_b = 0.0; } } /* Cleaning */ writer.flush(); writer.close(); in.close(); } catch (IOException e) { System.out.println(e); } } } 

He gets access to the label to the progressbar and progressbar through a link to the mlController controller mlController . My unsuccessful attempts to update the labels come after the comment /* Set Labels */ . Tell me how best to do this?

    1 answer 1

    The basic idea is that your downloadFile method should be called in a separate thread, not in the JavaFX Application Thread, and changes to the UI elements should be wrapped in Platform.runLater (() -> {...}). You can go ahead and make a separate Task, which does all the work, and has the message and progress properties, which can be labeled.

     public class App extends Application { public static void main(String[] args) throws Exception { launch(args); } public void start(Stage stage) throws Exception { VBox rootNode = new VBox(); Label label = new Label(); ProgressIndicator progressIndicator = new ProgressIndicator(); Button button = new Button(); button.setOnAction((e) -> { DownloadTask downloadTask = new DownloadTask(); label.textProperty().bind(downloadTask.messageProperty()); progressIndicator.progressProperty().bind(downloadTask.progressProperty()); Thread th = new Thread(downloadTask); th.setDaemon(true); th.start(); }); rootNode.getChildren().add(label); rootNode.getChildren().add(progressIndicator); rootNode.getChildren().add(button); Scene scene = new Scene(rootNode, 400, 200); stage.setTitle("App"); stage.setScene(scene); stage.show(); } class DownloadTask extends Task<Void> { @Override protected Void call() throws Exception { for (int i = 0; i < 100; i++) { updateMessage("Progress " + i); updateProgress(i, 100); Thread.sleep(10); } return null; } } 

    }

    • Thanks for the answer. There is a problem if running Task<> with updateProgress() not from FX Thread throws an exception (I don’t remember exactly which, it says that you can only update UI from FX Thread). Moreover, this does not apply to tasks with updateMessage() , for some reason they work. I did this: I started the download in a separate thread (so that the interface does not hang while loading large files) and added Platform.runLater(() -> progressBarName.setProgress(x)); to the download method Platform.runLater(() -> progressBarName.setProgress(x)); . I painted all this, of course, not for you, but more for people like me) Here is a link to what happened: pastebin.com/JxcQyvE0 - Lurking Elk
    • Please write what you think about the code by reference ( pastebin.com/JxcQyvE0 ), how you would do, etc. - Lurking Elk 3:12 pm
    • one
      I would disconnect from the need to transfer the controller, transfer all the download work to Task. gist.github.com/russ-p/63d24c18fb9a702274df4e256d57c072 Still it would be worth looking at javafx.concurrent.Service. - Ruslan P.