user interface - ProgressBar en Javafx no se actualiza en el bloque onAction
user-interface (2)
Está bloqueando el hilo del evento javafx, necesita hacer el trabajo en otro hilo y sincronizar solo la llamada setProgress con Platform.runLater
Me gustaría tener una barra de progreso que se actualice dentro de un bloque
onAction
.
Por alguna razón en el siguiente código, la barra de progreso no se actualiza hasta que sale del bloque
onAction
.
No obtengo progreso durante nueve segundos y luego 90%.
El
System.out
imprime muy bien.
package net.snortum.play;
import javafx.application.Application;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
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.ProgressBar;
import javafx.scene.layout.GridPane;
import javafx.scene.layout.HBox;
import javafx.scene.text.Text;
import javafx.stage.Stage;
public class ProgressBarTester extends Application {
public static void main( String[] args ) {
launch( ProgressBarTester.class, args );
}
@Override
public void start( final Stage stage ) throws Exception {
final GridPane grid = new GridPane();
grid.setAlignment( Pos.CENTER );
grid.setHgap( 10 );
grid.setVgap( 10 );
grid.setPadding( new Insets( 25, 25, 25, 25 ) );
final Text title = new Text( "Test Progress Bar" );
int col = 0, row = 0, colSpan = 2, rowSpan = 1;
grid.add( title, col, row, colSpan, rowSpan );
col = 0;
row++;
grid.add( new Label( "Progress:" ), col, row );
col = 1;
final ProgressBar progress = new ProgressBar( 0.0 );
grid.add( progress, col, row );
final HBox hbox = new HBox();
hbox.setAlignment( Pos.BASELINE_RIGHT );
final Button submit = new Button( "Go" );
hbox.getChildren().add( submit );
col = 1;
row++;
grid.add( hbox, col, row );
submit.setOnAction( new EventHandler<ActionEvent>() {
@Override
public void handle( ActionEvent event ) {
double size = 10.0;
for (double i = 0.0; i < size; i++){
progress.setProgress( i / size );
System.out.printf("Complete: %02.2f%n", i * 10);
try {
Thread.sleep(1000);
} catch(InterruptedException ex) {
Thread.currentThread().interrupt();
}
}
}
} );
final Scene scene = new Scene( grid );
stage.setScene( scene );
stage.setTitle( "Test Progress Bar" );
stage.show();
}
}
Forma larga de la respuesta precisa de tomsomtom:
Si utiliza JavaFX Thread para hacer este tipo de trabajo a largo plazo, detiene la actualización de la interfaz de usuario, etc. Por lo tanto, debe ejecutar su trabajador en un hilo disperso. Si se ejecuta en un subproceso independiente, todas las operaciones de la GUI, como progress.setProgress (), deben devolverse al subproceso JavaFX mediante runLater (), ya que JavaFX no es multiproceso.
Prueba esto en tu acción:
submit.setOnAction( new EventHandler<ActionEvent>() {
@Override
public void handle( ActionEvent event ) {
double size = 10.0;
new Thread(){
public void run() {
for (double i = 0.0; i < size; i++){
final double step = i;
Platform.runLater(() -> progress.setProgress( step / size ));
System.out.printf("Complete: %02.2f%n", i * 10);
try {
Thread.sleep(1000);
} catch(InterruptedException ex) {
Thread.currentThread().interrupt();
}
}
}
}.start();
}
} );