Uploaded image for project: 'JDK'
  1. JDK
  2. JDK-8204949

Invalid JavaFX element rendering after binding disableProperty on Java 10

XMLWordPrintable

    • b15
    • 10
    • x86_64
    • generic

      ADDITIONAL SYSTEM INFORMATION :
      Windows 10 x64 Pro 1709 & 1803
      Java 10u1 x64 (both on JDK and JRE, explicitly targeting executables) - issue can be observed
      Java 8u172 x64 (both on JDK and JRE, explicitly targeting executables) - works fine

      A DESCRIPTION OF THE PROBLEM :
      Consider the following Java FX code, where "b" starts invisible: a.disableProperty().bind(b.visibleProperty())

      If an application utilizing such code is run on Java 10 VM, then from the first time "b" becomes visible, "a" will always be rendered as if it was disabled.

      Of course, during the time while "a" is not really disabled (despite being rendered with a gray overlay), you can still interact with that element. E.g. you can edit text in input controls, click buttons/links and so on, the events get propagated correctly and so on.

      If the application is run on Java 8 VM, it works as expected.

      REGRESSION : Last worked in version 8u172

      STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
      Compile and run the provided source code on a Java 10 VM. The provided JavaFX application explains itself.

      1. Click the button labelled "Click to reproduce". A new pane opens.
      2. Reopen the previous pane in the accordion.

      EXPECTED VERSUS ACTUAL BEHAVIOR :
      EXPECTED -
      The text field and button in the initial pane should appear enabled (they do with Java 8u172).
      ACTUAL -
      The text field and button in the initial pane appear disabled.
      Purely cosmetic, you can still use them as they are, in fact, enabled.

      ---------- BEGIN SOURCE ----------
      package application;

      import javafx.application.Application;
      import javafx.concurrent.Task;
      import javafx.stage.Stage;
      import javafx.scene.Scene;
      import javafx.scene.control.Accordion;
      import javafx.scene.control.Button;
      import javafx.scene.control.Label;
      import javafx.scene.control.TextField;
      import javafx.scene.control.TitledPane;
      import javafx.scene.layout.VBox;

      public class Main extends Application {
      @Override
      public void start(Stage primaryStage) {
           System.out.println("Executing start(Stage) in " + Thread.currentThread().getName());
      try {
      TextField invalidRenderField = new TextField();
      Button invalidRenderButton = new Button("Click to reproduce");
      Label propertyProvider = new Label();
      propertyProvider.setVisible(false);
      VBox invalidRenderParent = new VBox(invalidRenderField, invalidRenderButton, propertyProvider);
      TitledPane invalidRenderPane = new TitledPane("Incorrectly rendered elements", invalidRenderParent);
      Accordion root = new Accordion(invalidRenderPane);
      root.setExpandedPane(invalidRenderPane);

      invalidRenderField.disableProperty().bind(propertyProvider.visibleProperty());
      invalidRenderButton.disableProperty().bind(propertyProvider.visibleProperty());
      invalidRenderButton.setOnAction(e -> {
      System.out.println("Executing 1st onAction(ActionEvent) in " + Thread.currentThread().getName());

      propertyProvider.setVisible(true);
      propertyProvider.setText("At this point of time you cannot modify the field or click the button");

      Task<Void> task = new Task<>() {
      @Override
      protected Void call() throws Exception {
      System.out.println("Executing non-JFX code in " + Thread.currentThread().getName());
      Thread.sleep(3_000L);
      return null;
      }
      };
      task.setOnSucceeded(e2 -> {
      System.out.println("Executing onSuccess(WorkerStateEvent) in " + Thread.currentThread().getName());

      propertyProvider.setVisible(false);

      Label infoLabel = new Label("Either click the button below or just select the previous pane within the accordion");
      Button closePlaceholderButton = new Button("View failure");
      VBox placeholder = new VBox(infoLabel, closePlaceholderButton);
      TitledPane placeholderPane = new TitledPane("Placeholder", placeholder);

      closePlaceholderButton.setOnAction(e3 -> {
      System.out.println("Executing 2nd onAction(ActionEvent) in " + Thread.currentThread().getName());
      root.getPanes().remove(placeholderPane);
      root.setExpandedPane(invalidRenderPane);
      });

      root.getPanes().add(1, placeholderPane);
      root.setExpandedPane(placeholderPane);
      });
      new Thread(task, "WhateverThread").start();
      });

      Scene scene = new Scene(root, 800, 450);
      primaryStage.setScene(scene);
      primaryStage.show();
      } catch (Exception e) {
      e.printStackTrace();
      }
      }

      public static void main(String[] args) {
           System.out.println("Executing main(String[]) in " + Thread.currentThread().getName());
      launch(args);
      }
      }

      ---------- END SOURCE ----------

      CUSTOMER SUBMITTED WORKAROUND :
      The nodes in question will be rendered correctly if this code is added (for each affected node):

      node.disableProperty().addListener((observable, oldValue, newValue) -> {
          if (!newValue) { // if no longer disabled
              node.applyCss();
          }
      });

      FREQUENCY : always


            pmangal Priyanka Mangal (Inactive)
            webbuggrp Webbug Group
            Votes:
            0 Vote for this issue
            Watchers:
            2 Start watching this issue

              Created:
              Updated:
              Resolved: