ADDITIONAL SYSTEM INFORMATION :
OS Name: Microsoft Windows 11 Pro
OS Version: 10.0.22631 N/A Build 22631
openjdk version "21.0.4" 2024-07-16 LTS
OpenJDK Runtime Environment Corretto-21.0.4.7.1 (build 21.0.4+7-LTS)
OpenJDK 64-Bit Server VM Corretto-21.0.4.7.1 (build 21.0.4+7-LTS, mixed mode, sharing)
JavaFX Version 22.0.1 (gradle project)
(!) Sorry I could not update to JavaFX 24 or 25, this would need Java update, which I cannot do right now
A DESCRIPTION OF THE PROBLEM :
If the Tabs are added/removed (especially in quick successiion), at some time TabPane goes into "wrong" state and stops repainting itself.
STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
See the minimal test case provided.
When I click +/- buttons (especially quick enough), the TabPane stops repainting itself and looks like frozen. The component can be "unfrozen" through moving any SplitPane or resizing the window.
(!) Found a workaround (originating from https://stackoverflow.com/questions/47616221/javafx-tabpane-tabs-dont-update-position):
tabPane.setStyle("-fx-close-tab-animation: NONE; -fx-open-tab-animation: NONE;");
EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
TabPane stops repainting itselfs
ACTUAL -
TabPane reacts on Tabs being added/removed and on clicks on Tabs.
---------- BEGIN SOURCE ----------
import javafx.animation.AnimationTimer;
import javafx.application.Application;
import javafx.beans.binding.Bindings;
import javafx.geometry.Orientation;
import javafx.scene.Scene;
import javafx.scene.canvas.Canvas;
import javafx.scene.canvas.GraphicsContext;
import javafx.scene.control.*;
import javafx.scene.layout.HBox;
import javafx.scene.layout.StackPane;
import javafx.scene.layout.VBox;
import javafx.scene.paint.Color;
import javafx.stage.Stage;
public class Tmp extends Application {
public static void main(String[] args) {
Tmp.launch(args);
}
@Override
public void start(Stage stage) {
ResizableCanvas canvas = new ResizableCanvas();
StackPane pane = new StackPane(canvas);
TabPane tabPane = new TabPane();
tabPane.getTabs().add(createTab("1"));
SplitPane splitButtonsTabPane = new SplitPane(new TextArea("placeholder"), tabPane);
Button btnAdd = new Button("+");
btnAdd.setOnAction(evt -> tabPane.getTabs().add(createTab(String.format("%d", tabPane.getTabs().size() + 1))));
Button btnRemove = new Button("-");
btnRemove.disableProperty().bind(Bindings.isEmpty(tabPane.getTabs()));
btnRemove.setOnAction(evt -> tabPane.getTabs().removeLast());
VBox panelBelow = new VBox(splitButtonsTabPane, new HBox(btnAdd, btnRemove));
SplitPane splitAboveBelow = new SplitPane(pane, panelBelow);
splitAboveBelow.setOrientation(Orientation.VERTICAL);
Scene scene = new Scene(splitAboveBelow);
stage.setScene(scene);
stage.show();
new RedrawTimer(() -> redraw(canvas)).start();
}
private void redraw(Canvas canvas) {
GraphicsContext gc = canvas.getGraphicsContext2D();
gc.clearRect(0, 0, canvas.getWidth(), canvas.getHeight());
gc.setLineWidth(1);
gc.setStroke(Color.GREEN);
gc.strokeRect(10, 10, 50, 50);
gc.setStroke(Color.RED);
gc.strokeRect(0, 0, canvas.getWidth(), canvas.getHeight());
}
private Tab createTab(String name) {
Tab result = new Tab(name);
result.setContent(new Label(name));
return result;
}
// https://stackoverflow.com/questions/24533556/how-to-make-canvas-resizable-in-javafx
private static class ResizableCanvas extends Canvas {
@Override
public boolean isResizable() {
return true;
}
@Override
public double maxHeight(double width) {
return Double.POSITIVE_INFINITY;
}
@Override
public double maxWidth(double height) {
return Double.POSITIVE_INFINITY;
}
@Override
public double minWidth(double height) {
return 1D;
}
@Override
public double minHeight(double width) {
return 1D;
}
@Override
public void resize(double width, double height) {
this.setWidth(width);
this.setHeight(height);
}
}
private static class RedrawTimer extends AnimationTimer {
private final Runnable runnable;
public RedrawTimer(Runnable runnable) {
this.runnable = runnable;
}
@Override
public void handle(long now) {
runnable.run();
}
}
}
---------- END SOURCE ----------
OS Name: Microsoft Windows 11 Pro
OS Version: 10.0.22631 N/A Build 22631
openjdk version "21.0.4" 2024-07-16 LTS
OpenJDK Runtime Environment Corretto-21.0.4.7.1 (build 21.0.4+7-LTS)
OpenJDK 64-Bit Server VM Corretto-21.0.4.7.1 (build 21.0.4+7-LTS, mixed mode, sharing)
JavaFX Version 22.0.1 (gradle project)
(!) Sorry I could not update to JavaFX 24 or 25, this would need Java update, which I cannot do right now
A DESCRIPTION OF THE PROBLEM :
If the Tabs are added/removed (especially in quick successiion), at some time TabPane goes into "wrong" state and stops repainting itself.
STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
See the minimal test case provided.
When I click +/- buttons (especially quick enough), the TabPane stops repainting itself and looks like frozen. The component can be "unfrozen" through moving any SplitPane or resizing the window.
(!) Found a workaround (originating from https://stackoverflow.com/questions/47616221/javafx-tabpane-tabs-dont-update-position):
tabPane.setStyle("-fx-close-tab-animation: NONE; -fx-open-tab-animation: NONE;");
EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
TabPane stops repainting itselfs
ACTUAL -
TabPane reacts on Tabs being added/removed and on clicks on Tabs.
---------- BEGIN SOURCE ----------
import javafx.animation.AnimationTimer;
import javafx.application.Application;
import javafx.beans.binding.Bindings;
import javafx.geometry.Orientation;
import javafx.scene.Scene;
import javafx.scene.canvas.Canvas;
import javafx.scene.canvas.GraphicsContext;
import javafx.scene.control.*;
import javafx.scene.layout.HBox;
import javafx.scene.layout.StackPane;
import javafx.scene.layout.VBox;
import javafx.scene.paint.Color;
import javafx.stage.Stage;
public class Tmp extends Application {
public static void main(String[] args) {
Tmp.launch(args);
}
@Override
public void start(Stage stage) {
ResizableCanvas canvas = new ResizableCanvas();
StackPane pane = new StackPane(canvas);
TabPane tabPane = new TabPane();
tabPane.getTabs().add(createTab("1"));
SplitPane splitButtonsTabPane = new SplitPane(new TextArea("placeholder"), tabPane);
Button btnAdd = new Button("+");
btnAdd.setOnAction(evt -> tabPane.getTabs().add(createTab(String.format("%d", tabPane.getTabs().size() + 1))));
Button btnRemove = new Button("-");
btnRemove.disableProperty().bind(Bindings.isEmpty(tabPane.getTabs()));
btnRemove.setOnAction(evt -> tabPane.getTabs().removeLast());
VBox panelBelow = new VBox(splitButtonsTabPane, new HBox(btnAdd, btnRemove));
SplitPane splitAboveBelow = new SplitPane(pane, panelBelow);
splitAboveBelow.setOrientation(Orientation.VERTICAL);
Scene scene = new Scene(splitAboveBelow);
stage.setScene(scene);
stage.show();
new RedrawTimer(() -> redraw(canvas)).start();
}
private void redraw(Canvas canvas) {
GraphicsContext gc = canvas.getGraphicsContext2D();
gc.clearRect(0, 0, canvas.getWidth(), canvas.getHeight());
gc.setLineWidth(1);
gc.setStroke(Color.GREEN);
gc.strokeRect(10, 10, 50, 50);
gc.setStroke(Color.RED);
gc.strokeRect(0, 0, canvas.getWidth(), canvas.getHeight());
}
private Tab createTab(String name) {
Tab result = new Tab(name);
result.setContent(new Label(name));
return result;
}
// https://stackoverflow.com/questions/24533556/how-to-make-canvas-resizable-in-javafx
private static class ResizableCanvas extends Canvas {
@Override
public boolean isResizable() {
return true;
}
@Override
public double maxHeight(double width) {
return Double.POSITIVE_INFINITY;
}
@Override
public double maxWidth(double height) {
return Double.POSITIVE_INFINITY;
}
@Override
public double minWidth(double height) {
return 1D;
}
@Override
public double minHeight(double width) {
return 1D;
}
@Override
public void resize(double width, double height) {
this.setWidth(width);
this.setHeight(height);
}
}
private static class RedrawTimer extends AnimationTimer {
private final Runnable runnable;
public RedrawTimer(Runnable runnable) {
this.runnable = runnable;
}
@Override
public void handle(long now) {
runnable.run();
}
}
}
---------- END SOURCE ----------