0

Trying to describe in a JavaFX project the work of an increment loop on a TextField and TextArea nodes with an array of integers, I got to output each step of this increment.

As a short illustration, let’s say we have a tiny array of strings 6, 2, 74, 64 and 12. Used inside our for loop, an AppendText method immediately displays a final full array of integers while what I need is to show how my array gradually grows and how integers pop up one by one, at first 6, then 2 and so on until we obtain a complete array. Just as we can do it in console.

I am looking for an information on how to realize this in JavaFX or what to learn to be able to do it.

Any concrete, kind and illustrative advises would be mostly welcome.


Update: My question was marked as a possible duplicate of another question.

On this subject note please that what I expected was to reproduce a gradual display of JavaFX array and nothing else, not to update one single element of the array, as was asked in another question whose duplicate my own thread is suspected to be. Updating of one element and updating of the whole array of elements, will these things sound the same ("duplicate") to anybody?

So:

A. As explained above, our questions are different;

B. It is doubly wrong to declare my question a duplicate because its answer makes use of the same concept (Task class) as does the answer to another question, otherwise we could also mark my question as duplicate to all other stack overflow threads, comments from which I used to find myself a solution to my question (for example the one on initialization and the use of Strings assigned to Arrays in and outside Java loops, the link to that thread being available on request).

Questions and answers are well understood to be independent parts of human dialectics, i.e. similarity of answers (especially only a partial one, what was the case with my answer) in no way leads to a similarity of questions.

PS: Please understand questions before marking them as duplicates.

PS2: The question is already solved, but to comply with this site's rules I'll respect 48 hours limit before accepting the answer.

TomateFraiche
  • 134
  • 1
  • 2
  • 11
  • Possible duplicate of [JavaFx - Updating GUI](http://stackoverflow.com/questions/26554814/javafx-updating-gui) – fabian Jan 05 '16 at 09:42

2 Answers2

0

This answer assumes you want to add a delay, since appendText works for text output without delay.

If you want to show updates of a long-running task in the ui instead, simply run that task on a non-application thread and use Platform.runLater to update the text.

To show the text after a specific delay could use a Timeline to update text property (I use a List for simplicity):

static void showListGradually(List<?> list, StringProperty outputProperty, Duration delay) {
    // timeline updates text property to non-empty sublists
    Timeline timeline = new Timeline(new KeyFrame(delay, new EventHandler<ActionEvent>() {

        int sublistSize = 1;

        @Override
        public void handle(ActionEvent event) {
            outputProperty.set(list.subList(0, sublistSize++).toString());
        }

    }));
    timeline.setCycleCount(list.size());

     // No need to use Platform.runLater here, if this is the application thread
    Platform.runLater(() -> {
        // set initial value from fx application thread
        outputProperty.set(Collections.EMPTY_LIST.toString());

        timeline.play();
    });
}

The showListGradually method is used e.g. this way:

showListGradually(Arrays.asList(6, 2, 74, 64, 12), textField.textProperty(), Duration.seconds(1));
fabian
  • 80,457
  • 12
  • 86
  • 114
  • Thank you very much but I get an error after reproducing your code exactly as it is, the application is refusing to accept a new EventHandler declaration for KeyFrame. A **screenshot** of my Eclipse window is available by the following link - http://wikisend.com/download/763344/ERROR_PRINTSCREEN.jpg – TomateFraiche Jan 03 '16 at 23:04
  • @TomateFraiche: Make sure to use the correct class: [`javafx.event.EventHandler`](https://docs.oracle.com/javase/8/javafx/api/javafx/event/EventHandler.html) and not `java.beans.EventHandler` or some other `EventHandler` class. BTW: Eclipse should show you the javadocs for the `KeyFrame` constructors and you can find out the correct class there. There's more than one class in javafx has the same name as a swing/awt/ect. class. – fabian Jan 04 '16 at 09:33
  • Thanks for the reminder on imported classes' names repetitions.The code does not crash now but **how practically am I supposed to use it** and this timeline class to link to or to pass them into my javafx textfield or textarea? I'm not sure if I should use your delay here.I don't need to delay the output of the full array. I expect simply to display in a TextField(TextArea) the updating of a number of integers: first 6, then - 6, 2, then - 6, 2, 74 up until - 6, 2, 74, 64, 12 (as it was presented in the description). The same way as it works in console. Nothing more elaborate than that. – TomateFraiche Jan 04 '16 at 12:43
0

For people having similar questions:

I came up with a solution to my own question by implementing a Task class.

In particular, I:

  1. Initialized an empty String before an increment loop and then
  2. Placed in the loop a standard updateMessage method from Task class by
  3. Parameterizing it with that initialized empty String, assigned to itself added to the corresponding integer of my array.
  4. Set up a Thread pause action to make the gradual displaying of integers slower, so more pleasant to look at and more noticeable,
  5. Declared a Task messageProperty listener and
  6. Set up this listener as a parameter for my TextField setText method

This way every time the loop runs, it does exactly what I expect - it adds new integers in real time to a set of already existing and displayed ones.

Below are a link to a tiny screen catch video of how does the application's work look - https://youtu.be/VVwcP2Xlo18 and a part of my code relative to the above-mentioned description:

    backgroundUpdate.setOnAction(event -> {
                    tf1.setText("");            
        // Declare a Task class
        Task<Void> task = new Task<Void>() {

            // Override (declare) call method
            @Override
            public Void call() throws Exception {

                // Instantiate an empty string
                String lineOfData = "";
                int[] array1 = { 6, 2, 74, 64, 12 };

                // Loop through your array of integers
                for (int i = 0; i <= array1.length; i++) {
                    // Pause the loop
                    Thread.sleep(500);

        // Parameterize the standard 'updateMessage' method of Task class
        // Do this by assigning the initialized-above empty string incremented
        // by an Integer from declared-above array of integers, previously
        // converted into String value
                    updateMessage(lineOfData = lineOfData + (String.valueOf(array1[i])) + " ");
                }
                return null;
            }
        };
        // Add a listener on messageProperty
        task.messageProperty().addListener((obs, oldMessage, newMessage) ->

        // Set the textfield's text to new message of your listener
        tf1.setText(newMessage));
        new Thread(task).start();
    });
TomateFraiche
  • 134
  • 1
  • 2
  • 11