JDK-8365025 : Tree/TableView unexpectedly shows horizontal scrollbar with custom resize policy and unsnapped column width
  • Type: Bug
  • Component: javafx
  • Sub-Component: controls
  • Affected Version: jfx25
  • Priority: P4
  • Status: Open
  • Resolution: Unresolved
  • Submitted: 2025-08-07
  • Updated: 2025-08-08
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
tbdUnresolved
Related Reports
Relates :  
Description
Applying a custom resize policy that doesn't extend from ConstrainedColumnResizeBase to a tableView control, that allows showing the horizontal scrollbar when the width of the stage is lower than the minimum width of the tableView (as sum of the minimum width of its visible columns), would resize the columns width when the stage gets resized, but it shouldn't show the scrollbar when the width of the stage is bigger.

When the column width is not properly snapped, the horizontal scrollbar shows up unexpectedly, flickering (showing up and hiding repeatedly) as the stage gets resized. This can be reproduced on macOS and Windows, under any screen render scale.

When the column width is snapped (with either Math.ceil, Math.floor, TableView::snapSizeX, TableView::snapSpaceX or TableView::snapPositionX), the horizontal scrollbar doesn't show up anymore on macOS (render scale 2.0) or Windows (render scale 1.0 or 2.0), but keeps showing up with fractional scales on Windows (1.25, 1.50, 1.75).

The workaround for fractional scales found so far is to use an adapted version of the private Region::snapPortionX, that uses ScaledMath::floor instead of the other snap public methods that use round or ceil.

To reproduce the issue, run the attached test case with any recent JavaFX version (after 25-ea+7, to include the recent fix for JDK-8299753), on macOS or Windows.

Start resizing the stage, enlarging it, and see how the horizontal scrollbar shows up ("TableView with ScrollBar.png") and hides ("TableView without ScrollBar.png").

Then change TEST_OPTION from 0 to any of 1 to 6 values. Running on macOS or Windows with render scales 1.0 and 2.0 will work (no scrollbar shown when stage width is bigger than minimum table width), and it will still fail on Windows with fractional scales 1.25, 1.50 or 1.75.

Finally, set TEST_OPTION to 7, and it will work on all platforms with any render scale.
Comments
Good point. If I understand you correctly, the custom resize policy then needs to floor the column sizes - something that it can already do, by declaring its own equivalent of Region::snapPortionX, as in TEST_OPTION=7. Minor comment: you may want to do snapPortionX after Math.min(): ``` double w2 = snapPortionX(Math.min(widthLeft, w)); rf.setColumnWidth(visibleLeafColumns.get(i), w2); widthLeft -= w; ``` Btw, I wanted to make the Region::snapPortionX/Y public in https://github.com/openjdk/jfx/pull/1190 , explaining why it's needed (see https://bugs.openjdk.org/browse/JDK-8299753 ), but it was eventually shot down.
07-08-2025

There are design requirements for this case that need the horizontal scrollBar to show up when the size of the stage is too small and the columns can't be shrunk below their minimum width, and that can't be achieved with ConstrainedColumnResizeBase, as it removes completely such scrollbar. Developers are still free to use Callback because ConstrainedColumnResizeBase is not mandatory, and the styling via pseudo classes only applies to the built-in policies in ConstrainedColumnResize, not to the custom extensions of ConstrainedColumnResizeBase, right? So I'd say this is still a valid case, because it is still possible to be designed (even if it might not follow the best practices) and developers can still run into it.
07-08-2025

I am afraid this is a non-issue: one *must* extend ConstrainedColumnResizeBase in order to get the constrained resize behavior. The reason for this is twofold: 1. Backward compatibility. The original design used Callback for column resizing, a construct too simple to allow for extension. So instead, we introduced a marker base class ConstrainedColumnResizeBase to communicate the fact that it is, in fact, a constrained policy. 2. The styling is different when a constrained policy is in effect. This is reflected in ConstrainedColumnResizeBase::toString() method returning a CSS class name (yikes!) A better design would have used a dedicated interface which could be extended with ::isConstrained() etc. All you need to do in the example is ``` private static class UserDefinedResizePolicy extends ConstrainedColumnResizeBase implements Callback<TableView.ResizeFeatures, Boolean> { ```
07-08-2025

oops, had the Attachments section collapsed... sorry. all good.
07-08-2025

It is already attached, isn't it? https://bugs.openjdk.org/secure/attachment/115741/TableViewResizeTest.java
07-08-2025

Please attach a test case, [~jpereda]
07-08-2025