Empresas
Empregos
  • Sobre nós
  • Soluções
    • Publicação de vagas
      Publique sua vaga e receba candidatos qualificados em 48h.
    • Avaliações de candidatos
      Mais de 500 testes técnicos e psicológicos, mais anti-fraude.
    • Headhunting
      Busca executiva personalizada do início ao fim.
    • Folha de Pagamento + EOR
      Dispersão de folha e EOR em mais de 15 países da LATAM.
  • Preços
  • Empregos

0

217
Visualizações
Restablecer selección de casilla de verificación en ChangeListener bajo condición

En mi aplicación JavaFX, estoy usando Checkboxes de verificación en TreeView para cambiar la visibilidad de los nodos.

  • casilla de verificación seleccionada = algunos nodos son visibles
  • casilla de verificación deseleccionada = algunos nodos son invisibles

Sin embargo, en un caso especial, se debe solicitar al usuario que confirme su selección, ya que pueden surgir problemas al activar una casilla de verificación específica. Se abre una ventana de diálogo en la que el usuario puede elegir entre "Sí" y "No". Si el usuario elige "Sí", los nodos se vuelven visibles y todo está bien. Pero si el usuario elige "No", la casilla de verificación debe desmarcarse nuevamente.

Mi idea era verificar la condición (en este caso, presione "no" en una ventana de diálogo) en ChangeListener y, si es cierto, establezca el valor seleccionado en falso.

Pero por alguna razón, no funcionó. Después de eso, descubrí que funciona con el método refresh() de TreeView .

Preguntas

  1. ¿Por qué no funciona sin el método refresh() , por qué se ignora setSelected() ?
  2. ¿Debo usar el método refresh() ?
  3. ¿Hay una mejor solución para cambiar el estado de selección?

Ejemplo mínimo reproducible

El uso de la línea refresh() mostrará el comportamiento deseado: la casilla de verificación permanece sin seleccionar después de hacer clic porque 5> 4 (5>4 simula, por ejemplo, presionar "no" en una ventana de diálogo).

 import javafx.application.Application; import javafx.beans.value.ChangeListener; import javafx.scene.Scene; import javafx.scene.control.CheckBoxTreeItem; import javafx.scene.layout.VBox; import javafx.stage.Stage; import org.controlsfx.control.CheckTreeView; public class HelloApplication extends Application { enum Names { TEST1, TEST2, TEST3, TEST4 } private final CheckTreeView<String> checkTreeView = new CheckTreeView<>(); @Override public void start(Stage stage) { VBox vBox = new VBox(); Scene scene = new Scene(vBox, 500, 500); setTreeView(); vBox.getChildren().add(checkTreeView); stage.setScene(scene); stage.show(); } public static void main(String[] args) { launch(); } public void setTreeView() { CheckBoxTreeItem<String> rootItem = new CheckBoxTreeItem<>("Root"); rootItem.setExpanded(true); for (Names name : Names.values()) { CheckBoxTreeItem<String> item = new CheckBoxTreeItem<>(name.toString(), null); item.selectedProperty().addListener(this.onSelectionChanged(item)); rootItem.getChildren().add(item); } this.checkTreeView.setRoot(rootItem); } private ChangeListener<Boolean> onSelectionChanged(CheckBoxTreeItem<String> item) { return (observableValue, previousChoice, newChoice) -> { if (newChoice) { // if checkbox is selected // if anything happens... for example press a "no" button in a dialog window if (5 > 4) { System.out.println("reset checkbox status"); item.setSelected(previousChoice); } } // it works with refresh: // this.checkTreeView.refresh(); }; } }

EDITAR:

La solución de @VGR con

Platform.runLater(() -> item.setSelected(previousChoice));

funciona para el ejemplo reproducible mínimo, pero no parece ser la mejor manera de hacerlo. Como ya se discutió en los comentarios, con Platform.runLater() es

trabajando la mayor parte del tiempo

y

no hay garantía porque no se especifica el tiempo exacto, se interrumpirá si algo en los eventos pendientes también usa runlater.

Se desea una solución/solución alternativa que siempre funcione...

over 4 years ago · Santiago Trujillo
2 Respostas
Responde à pergunta

0

Está restableciendo el elemento de la casilla de verificación demasiado pronto. Todavía no ha terminado su procesamiento de eventos.

Desea esperar hasta que termine antes de restablecerlo. Use Platform.runLater para asegurarse de restablecerlo después de que se hayan procesado todos los eventos pendientes:

 Platform.runLater(() -> item.setSelected(previousChoice));
over 4 years ago · Santiago Trujillo Relatório

0

Lo que estamos viendo en el ejemplo de OP en realidad es el comportamiento estándar de las propiedades enlazadas bidireccionalmente, reducido a un ejemplo simple (sin interfaz de usuario, solo propiedades).

El escenario:

  • hay dos propiedades booleanas, que representan las propiedades seleccionadas data (checkBoxTreeItem) y ui (checkBox)
  • están conectados de la misma manera que en un checkBoxTreeCell, es decir, la interfaz de usuario está vinculada bidireccionalmente a los datos
  • un oyente de los datos revierte los datos a falso al recibir un cambio de falso -> verdadero

Solo para mostrar que, aunque no se recomienda, revertir el estado del remitente en un oyente está funcionando: establecemos la propiedad de datos en verdadero. Al final, tanto los datos como la interfaz de usuario son falsos como queremos.

 before data.set(true) state of data/ui: false / false enter listener to ui: true enter listener to data: true enter listener to ui: false enter listener to data: false ... returning listener to data - after reset false after data.set(true) - state of data/ui: false / false

Para la simulación real del contexto del OP: configure la propiedad ui (el usuario hace clic en la casilla de verificación); al final, la propiedad de datos se revierte mientras que la propiedad ui no. Técnicamente, eso se hace en BidireccionalBinding que ignora los cambios entrantes durante la actualización.

 before ui.set(true) state of data/ui: false / false enter listener to data: true enter listener to data: false ... returning listener to data - after reset false enter listener to ui: true after ui.set(true) - state of data/ui: false / true

El ejemplo:

 public class BidiBindingUpdating { public static void main(String[] args) { BooleanProperty data = new SimpleBooleanProperty(); BooleanProperty ui = new SimpleBooleanProperty(); ui.bindBidirectional(data); // listener to item: revert to false data.addListener((src, ov, nv) -> { System.out.println("enter listener to data: " + nv); if (!nv) { System.out.println(" ... returning"); return; } data.set(ov); System.out.println("listener to data - after reset " + data.get()); }); // listener to check: logging only ui.addListener((src, ov, nv) -> { System.out.println("enter listener to ui: " + nv); }); // set item directly: System.out.println("before data.set(true)"); System.out.println(" state of data/ui: " + data.get() + " / " + ui.get()); data.set(true); System.out.println("after data.set(true) - state of data/ui: " + data.get() + " / " + ui.get()); // set bound property: System.out.println("\nbefore ui.set(true)"); System.out.println(" state of data/ui: " + data.get() + " / " + ui.get()); ui.set(true); System.out.println("after ui.set(true) - state of data/ui: " + data.get() + " / " + ui.get()); } }
over 4 years ago · Santiago Trujillo Relatório
Responde à pergunta
Encontrar trabalhos remotos

Descubra a nova forma de encontrar um emprego!

melhores empregos
Principais categorias de trabalho
Empresas
Postar vaga Preços Comercial
Jurídico
Termos e Condições Política de privacidade
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Recomende algumas ofertas para mim
Preciso de ajuda