Cómo reparar el error en la representación javafx (ComboBox, Lista)

user27772:

En una aplicación bastante compleja javafx me enfrentaba a un posible error de representación. Los últimos dos días pude seguirle la pista a la siguiente aplicación sencilla. La siguiente SSCCE demuestra que en ciertas circunstancias, algunos componentes de JavaFX no se procesan correctamente. Como resultado, ComboBox y ListView no muestran contenido modificado:

import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.ComboBox;
import javafx.scene.control.Label;
import javafx.scene.control.ListView;
import javafx.scene.control.Tab;
import javafx.scene.control.TabPane;
import javafx.scene.control.TabPane.TabClosingPolicy;
import javafx.scene.layout.HBox;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;

public class ComboManagedBug extends Application {
  public static void main(String[] args) {
    launch(args);
  }

  public void start(Stage primaryStage) {
    // add combo box
    ComboBox<String> combo = new ComboBox<>();
    combo.setPromptText("Choose a value...");
    combo.getItems().setAll("1", "2", "3");

    // add list view
    ListView<Label> list = new ListView<>();

    // add "add" button
    Button add = new Button("Add");
    add.setOnAction(e -> list.getItems().add(
      new Label(combo.getSelectionModel().getSelectedItem())));

    // add tab pane
    Tab tab1 = new Tab("First", new VBox(combo, add, list));
    Tab tab2 = new Tab("Second");
    TabPane tabs = new TabPane(tab1, tab2);
    tabs.setTabClosingPolicy(TabClosingPolicy.UNAVAILABLE); // important!

    // add "next" and "cancel" buttons at bottom
    Button next = new Button("Next");
    Button cancel = new Button("Cancel (Triggers refresh)");
    HBox buttons = new HBox(next, cancel);

    // install tab listener
    tabs.getSelectionModel().selectedItemProperty().addListener((a, b, c) -> {
      // intention is to show next button only on first tab
      boolean firstTab = c == tab1;
      next.setVisible(firstTab);
      next.setManaged(firstTab); // important!
    });

    // show
    VBox root = new VBox(new VBox(tabs, buttons)); // important!
    Scene scene = new Scene(root, 400, 400);
    primaryStage.setTitle("ComboBox/ListView Rendering Bug Demo");
    primaryStage.setScene(scene);
    primaryStage.show();
  }
}

Pasos para reproducir:

  1. Ejecución de programas
  2. Elija combo valor -> muestra ComboBox valor elegido -> OK
  3. Haga clic en "Agregar" -> valor se agrega al ListView y se muestra -> OK
  4. Activar segunda pestaña
  5. Activar primera pestaña
  6. Elija un valor combinado de ser diferente a la anterior -> valor de ComboBox no cambia -> ERROR
  7. Haga clic en "Agregar" -> contenido ListView no cambia -> ERROR
  8. Haga clic en "Cancelar" en la parte inferior -> aunque no hubo oyente añadido a este botón, tanto el cuadro combinado y el ListView muestran los valores correctos ahora. Por lo tanto, ambos recipientes parecen contener los valores correctos pero no se procesan correctamente hasta que se active alguna refrescante interfaz de usuario.

Tenga en cuenta que hay tres reqiurements importantes para reproducir este error (marcado con "importantes"):

  1. Alternar conseguido estado del botón "Siguiente" al alternar las pestañas para ocultar este botón (forma habitual para ocultar un nodo junto con el estado visible del nodo, consulte JavaFX - setVisible no "ocultar" el elemento )
  2. TabClosingPolicy.UNAVAILABLE (un caso muy común)
  3. una caja vertical en una caja vertical (que puede ocurrir fácilmente en la vida real cuando se anidan diferentes nodos de componentes javafx).

Este error es ya conocido, y ¿alguien sabe una solución para esto? Probé Platform.runLater (cancel.fire ()) y cosas similares, pero sin éxito.

Gracias por cualquier insinuación, Peter.

Por cierto., Aparte de esto, nuestros usos de la empresa JavaFX desde hace algunos años. En nuestra experiencia, es muy fiable y javafx programación es divertido. Espero que haya una solución sencilla para nuestro problema :)

user27772:

Como se discutió en los comentarios del post original, el error no se produce en JavaFX 8 (Oracle), pero en versiones posteriores (OpenJFX). He encontrado la siguiente solución:

public static void fixTabRendering(TabPane tabs) {
    if (tabs.getTabClosingPolicy() != TabClosingPolicy.UNAVAILABLE) return;
    tabs.setTabClosingPolicy(TabClosingPolicy.SELECTED_TAB);
    for (Node node : tabs.lookupAll(".tab-close-button")) {
        // hide "close" button to imitate TabClosingPolicy.UNAVAILABLE
        node.setStyle("-fx-background-color:transparent;-fx-shape:null;-fx-pref-width:0.001");
    }
}

Este código se debe ejecutar después de mostrar la etapa (de lo contrario lookupAll () vuelve nula ), así como después de añadir pestañas para el panel de la pestaña. Este último se podría lograr a través de un oyente pestaña:

tabs.getTabs().addListener((Change<?> change) ->
    Platform.runLater(() -> fixTabRendering(tabs)));

Platform.runLater () es necesaria porque de lo contrario lookupAll () no puede devolver los nodos de las pestañas añadido.

Tal vez esta solución puede ayudar a alguien :)

Supongo que te gusta

Origin http://43.154.161.224:23101/article/api/json?id=336128&siteId=1
Recomendado
Clasificación