Necesita aclaración sobre el cambio de datos en el hilo de la aplicación javafx

He estado migrando un proyecto mío a JavaFX y comencé a encontrar problemas de subprocesos. Adjuntaré un breve ejemplo. Después de mucho buscar logré resolver el problema. No puedo cambiar los datos de tableView fuera del hilo de la aplicación fx. Cambié mi código de usar SwingWorker a una tarea.

Al principio, eso funcionó hasta que agregué un oyente de cambio a la lista observableList de la tabla. Luego recibí el error "No en el hilo de la aplicación FX";

El error ocurrió dentro del método onChanged cuando intenté actualizar el valor de una etiqueta. Resolví esto envolviéndolo dentro de Platform.runLater ().

Solo estoy confundido sobre por qué cambiar la etiqueta dice que no estaba en el hilo de la aplicación. ¿En qué hilo se estaba ejecutando esto? Además, ¿estoy agregando filas a mi tabla correctamente mediante una tarea? En mi aplicación real, podría agregar 50k filas, por lo tanto, el hilo separado para no bloquear la interfaz de usuario.

public class Temp extends Application{  
    private ObservableList<String> libraryList = FXCollections.observableArrayList();

    public void start(Stage stage) {

        Label statusLabel = new Label("stuff goes here");

        TableView<String> table = new TableView<String>(libraryList);
        table.setColumnResizePolicy(TableView.CONSTRAINED_RESIZE_POLICY);

        TableColumn<String, String> col = new TableColumn<String, String>("Stuff");
        col.setCellValueFactory(cellData -> new ReadOnlyStringWrapper(cellData.getValue()));
        table.getColumns().add(col);

        libraryList.addListener(new ListChangeListener<String>() {
            public void onChanged(Change change) {
                // Problem was caused by setting the label's text (prior to adding the runLater)
                Platform.runLater(()->{
                    statusLabel.setText(libraryList.size()+" entries");
                });                 
            }               
        });

        // dummy stuff
        libraryList.add("foo");
        libraryList.add("bar");

        Button b = new Button("Press Me");
        b.setOnAction(new EventHandler<ActionEvent>() {
            public void handle(ActionEvent e) {
                FileTask task = new FileTask();
                new Thread(task).start();
            }
        });

        BorderPane mainBody = new BorderPane();

        mainBody.setTop(statusLabel);
        mainBody.setCenter(table);
        mainBody.setBottom(b);
        Scene scene = new Scene(mainBody);
        stage.setScene(scene);
        stage.show();       
    }


    class FileTask extends Task<Boolean>{

        public FileTask(){

        }

        protected Boolean call() throws Exception{

            Random rand = new Random();
            for(int i = 0; i < 5; i++) {
                String s = ""+rand.nextInt(Integer.MAX_VALUE);
                libraryList.add(s);
            }

            return true;
        }   
    }     

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

    }
}
Respuesta 1

Funciona como se esperaba, tiene el hilo de la aplicación y el hilo de la tarea, se ven así:

App ------\ ----------------------
Task       \-label.setText() Exception

No puede hacer ningún trabajo de IU en otra cosa que no sea el hilo de la aplicación, por lo que agregar su RunLater hace esto:

App ----\ -------------/ RunLater(label.setText()) ----------
Task     \-add to list/

que funciona bien Hay algunas formas de administrar esto en función de lo que desea hacer:

  • Si desea actualizar la lista de la Tabla dentro de la Tarea, puede mover la llamada RunLater dentro de la tarea, en lugar de dentro del controlador, de esta manera todavía lo llevará de regreso al hilo de la aplicación. De esta manera, si realmente está en el hilo de la aplicación, no hay necesidad de llamar a RunLater dentro del controlador.
App ---\ -----------------------/ label.setText() ----------
Task    \-RunLater(add to list)/
  • Otra opción es usar una Tarea> que se ejecutará en el otro subproceso y devolver la lista completa de cadenas que se agregarán. Esto es más probable que desee si realiza llamadas de red en la tarea, obtenga una lista de elementos y luego agréguelos una vez que estén todos descargados en la tabla.
App -----\ ------------------------------/ label.setText() ---/ add to table list-------
Task      \-build list, update progress /- return final list /

Ojalá se mantenga el formato.

Respuesta: 2

En este momento, puedo obtener sonido de una línea normal: en el micrófono a través del puerto del micrófono. Sin embargo, no sé cómo accedería a una pieza de hardware directamente a través de Java para obtener sonido. ¿Alguien podría ayudar con esto? ...

Con el siguiente código, el script ingresa en el bloque de if (mySet! = Null) solo en la primera llamada del método. ¿Por qué desde la segunda llamada mySet resulta nulo? Mapa <Entero, Conjunto <Cadena, ...

Así que tengo una aplicación que usa archivos fuente Java y Kotlin (todos ubicados en el directorio / src / main / kotlin porque eventualmente queremos migrar a kotlin de todos modos) y eso genera un ...

¿Hay algún sitio con una explicación completa del algoritmo CLAHE y tal vez algún código de muestra? Hasta ahora solo he encontrado el código para matlab sin explicación y necesito implementar el mío (...