JDK-8207837 : Indeterminate ProgressBar does not animate if content is added after scene is set on window
  • Type: Bug
  • Component: javafx
  • Sub-Component: scenegraph
  • Affected Version: 9,10,openjfx11
  • Priority: P3
  • Status: Resolved
  • Resolution: Fixed
  • OS: generic
  • CPU: x86_64
  • Submitted: 2018-07-18
  • Updated: 2021-06-09
  • Resolved: 2019-01-22
The Version table provides details related to the release that this issue/RFE will be addressed.

Unresolved : Release in which this issue/RFE will be addressed.
Resolved: Release in which this issue/RFE has been resolved.
Fixed : Release in which this issue/RFE has been fixed. The release containing this fix may be available for download as an Early Access Release or a General Availability Release.

To download the current JDK release, click here.
Other
openjfx11.0.12Fixed
Related Reports
Relates :  
Relates :  
Description
ADDITIONAL SYSTEM INFORMATION :
java 10.0.2 2018-07-17
Java(TM) SE Runtime Environment 18.3 (build 10.0.2+13)
Java HotSpot(TM) 64-Bit Server VM 18.3 (build 10.0.2+13, mixed mode)

OS Name: Microsoft Windows 10 Home
OS Version: 10.0.17134 Build 17134

Graphics: Intel(R) HD Graphics 630

Computer is an Inspiron 5577 Dell laptop



A DESCRIPTION OF THE PROBLEM :
When a ProgressBar is indeterminate it is supposed to animated back and forth. When the ProgressBar is part of a Stage the animation works as expected. If you add the ProgressBar to a Dialog, however, the animation appears to be stuck at the start of the animation. This appears to only affect indeterminate ProgressBars (when the progress is updated to some determinate state the visuals update appropriately). May affect other animated nodes, such as ProgressIndicator, but did not test them.

Using early access builds for OpenJDK 11 with OpenJFX 11 does not solve the issue.

Issue has related question on Stack Overflow which indicates the issue is also present on a Mac computer.
https://stackoverflow.com/questions/51392810/indeterminate-progressbar-does-not-animate-when-part-of-a-dialog-javafx-10

REGRESSION : Last worked in version 8u181

STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
1. Create ProgressBar and set it to indeterminate progress
2. Add it to a Dialog (either via the graphic property or content property)
3. Display Dialog by calling dialog.show() or dialog.showAndWait()

EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
To see a blue rectangle animate side-to-side to indicate indeterminate progress.
ACTUAL -
The blue rectangle displays on the left side of the ProgressBar but does not animate.

---------- BEGIN SOURCE ----------
import javafx.application.Application;
import javafx.concurrent.Task;
import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.scene.Node;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.ButtonType;
import javafx.scene.control.Dialog;
import javafx.scene.control.Label;
import javafx.scene.control.ProgressBar;
import javafx.scene.layout.HBox;
import javafx.scene.layout.StackPane;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;
import javafx.stage.Modality;

public class Main extends Application {
	
	@Override
	public void start(Stage primaryStage) {
		Button detButton = new Button("Launch Determinate Task");
		detButton.setOnAction(ae -> {
			ae.consume();
			createDialog(primaryStage, true)
					.showAndWait();
		});
		
		Button indetButton = new Button("Launch Indeterminate Task");
		indetButton.setOnAction(ae -> {
			ae.consume();
			createDialog(primaryStage, false)
					.showAndWait();
		});
		
		HBox btnBox = new HBox(detButton, indetButton);
		btnBox.setSpacing(10);
		btnBox.setAlignment(Pos.CENTER);
		
		StackPane root = new StackPane(btnBox, createDummyProgressNode());
		
		Scene scene = new Scene(root, 500, 300);
		primaryStage.setScene(scene);
		primaryStage.setTitle("ProgressBar Issue");
		primaryStage.setResizable(false);
		primaryStage.show();
	}
	
	private Node createDummyProgressNode() {
		Label label = new Label("ProgressBar to show animation in Stage.");
		
		ProgressBar progressBar = new ProgressBar();
		progressBar.setMaxWidth(Double.MAX_VALUE);
		
		VBox box = new VBox(label, progressBar);
		box.setMaxHeight(VBox.USE_PREF_SIZE);
		box.setSpacing(3);
		box.setAlignment(Pos.CENTER_LEFT);
		box.setPadding(new Insets(5));
		
		StackPane.setAlignment(box, Pos.BOTTOM_CENTER);
		
		return box;
	}
	
	private Dialog<?> createDialog(Stage owner, boolean determinate) {
		Task<?> task = new BackgroundTask(determinate);
		
		Dialog<?> dialog = new Dialog<>();
		dialog.initOwner(owner);
		dialog.initModality(Modality.NONE);
		dialog.setTitle("Background Task - " 
				+ (determinate ? "Determinate" : "Indeterminate"));
		
		dialog.getDialogPane().setPrefWidth(300);
		dialog.getDialogPane().setContent(createDialogContent(task));
		
		dialog.getDialogPane().getButtonTypes().add(ButtonType.OK);
		dialog.getDialogPane().lookupButton(ButtonType.OK)
				.disableProperty().bind(task.runningProperty());
				
		dialog.setOnShown(de -> {
			de.consume();
			executeTask(task);
		});
		
		return dialog;
	}
	
	private Node createDialogContent(Task<?> task) {
		Label label = new Label();
		label.textProperty().bind(task.messageProperty());
		
		ProgressBar progressBar = new ProgressBar();
		progressBar.setMaxWidth(Double.MAX_VALUE);
		progressBar.progressProperty().bind(task.progressProperty());
		
		VBox box = new VBox(label, progressBar);
		box.setSpacing(3);
		box.setAlignment(Pos.CENTER_LEFT);
		
		return box;
	}
	
	private void executeTask(Task<?> task) {
		Thread thread = new Thread(task, "background-thread");
		thread.setDaemon(true);
		thread.start();
	}
	
	// Dummy Task to simulate long running background task
	private static class BackgroundTask extends Task<Void> {
		
		private final boolean determinate;
		
		private BackgroundTask(boolean determinate) {
			this.determinate = determinate;
		}
		
		@Override
		protected Void call() throws Exception {
			final int loops = 1_000;
			for (int i = 0; i <= loops; i++) {
				updateMessage("Running... " + i);
				Thread.sleep(1L);
				if (determinate) {
					updateProgress(i, loops);
				}
			}
			updateMessage("Complete");
			updateProgress(loops, loops);
			return null;
		}
		
	}
	
}
---------- END SOURCE ----------

CUSTOMER SUBMITTED WORKAROUND :
No workaround is known at this time.

FREQUENCY : always



Comments
Changeset: eedba0ab9a0b Author: kcr Date: 2019-01-22 09:08 -0800 URL: http://hg.openjdk.java.net/openjfx/jfx-dev/rt/rev/eedba0ab9a0b 8216377: Fix memoryleak for initial nodes of Window 8207837: Indeterminate ProgressBar does not animate if content is added after scene is set on window Summary: Add or remove the windowShowingChangedListener when the scene changes Reviewed-by: arapte, kcr Contributed-by: fk@sandec.de
22-01-2019

In that case, we can close this as a duplicate of JDK-8216377 once it is pushed.
18-01-2019

Hello Kevin, I also confirmed that the proposed fix for JDK-8216377 also fixes this bug.
14-01-2019

I have attached a simple test program, IndeterminateProgressBar.java, that reproduces the same bug (it is a simplified version of the program from JDK-8200239). The test program does the following, and the order is important: 1. Create a root node (I used a StackPane) 2. Create a scene using that root node 3. Set the scene on the stage 4. Create an indeterminate ProgressBar, and add it as a child of the root 5. Show the stage On JDK 8u192 it will animate fine. On JDK 9 and later, it will not animate. If the ProgressBar is added to the root before the the scene is added to the stage, then it work. The root cause of this bug is the same as JDK-8216377 (which is a memory leak). Namely, the windowShowingChangedListener is not added or removed when the node's scene changes, but only when the scene's window changes. I can confirm that the proposed fix for JDK-8216377 also fixes this bug. Both the original test program and the one I just attached work after applying the fix for JDK-8216377.
11-01-2019

Targeting for openjfx12. If a safe fix can be found before the RDP2 deadline, we might consider it for 11.
23-07-2018

Below two bug-fixes in 9b127 has change in ProgressIndicatorSkin, Blindly reverting these changes from ProgressIndicatorSkin,does not fix the issue. JDK-8151165: ProgressIndicator indeterminate transition initializated even in non visible controls JDK-8090322: Need new tree visible property in Node that consider Scene and Stage visibility
20-07-2018

Issue is reproducible in both windows and linux. Its a regression introduced in JDK 9+b127. Windows 10, 64-bit JDK results -------------------------- 8u20-b26: Pass 8u181-b13 : Pass 9+126 : pass 9+127 : Fail <== regression 9+181 : Fail 10.0.2 + 13 : Fail 11-ea+13 : Fail
19-07-2018