JDK-6510914 : JScrollBar.getMinimumSize() breaks the contract of JComponent.setMinimumSize()
  • Type: Bug
  • Component: client-libs
  • Sub-Component: javax.swing
  • Affected Version: 5.0u6
  • Priority: P4
  • Status: Resolved
  • Resolution: Fixed
  • OS: solaris_2.5.1
  • CPU: sparc
  • Submitted: 2007-01-09
  • Updated: 2024-02-27
  • Resolved: 2024-02-18
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.
JDK 23
23 b11Fixed
Related Reports
CSR :  
Description
The javadoc contract for JComponent.setMinimumSize(Dimension) states:

"Sets the minimum size of this component to a constant value. Subsequent calls to getMinimumSize will always return this value..."

However, JScrollBar overrides getMinimumSize() and breaks this contract - it always returns a minimum size derived from the preferred size even if you have previously called setMinimumSize().

Code to reproduce:

JScrollBar bar = new JScrollBar( SwingConstants.HORIZONTAL );
bar.setMinimumSize( new Dimension( 75, 0 ) );
System.out.println( bar.getMinimumSize() );

Expected: Prints "java.awt.Dimension[width=75,height=0]"
Actual: Prints "java.awt.Dimension[width=5,height=17]"

The code for JScrollBar.java contains this comment above the implementation of getMinimumSize():

// PENDING(hmuller) - the next three methods should be removed

Indeed, removing those three methods would fix this bug.

Comments
Changeset: 39627bc4 Author: Prasanta Sadhukhan <psadhukhan@openjdk.org> Date: 2024-02-18 16:14:33 +0000 URL: https://git.openjdk.org/jdk/commit/39627bc4296dc1cde83c7ef2f2ece1719015df64
18-02-2024

Does any demo app call JScrollBar.setMinimumSize, setMaximumSize or setPreferredSize? If not, you won't notice the difference.
06-11-2023

JScrollBar.getMinimumSize() is called from JFileChooser and JList demo in SwingSet2 JScrollBar.getMaximumSize() is not called from any demos in SwingSet2. In JFileChooser, getMinimumSize is called from at java.desktop/javax.swing.JScrollBar.getMinimumSize(JScrollBar.java:764) at java.desktop/javax.swing.ScrollPaneLayout.minimumLayoutSize(ScrollPaneLayout.java:653) at java.desktop/java.awt.Container.minimumSize(Container.java:1878) at java.desktop/java.awt.Container.getMinimumSize(Container.java:1862) at java.desktop/javax.swing.JComponent.getMinimumSize(JComponent.java:1816) at java.desktop/java.awt.BorderLayout.minimumLayoutSize(BorderLayout.java:668) at java.desktop/java.awt.Container.minimumSize(Container.java:1878) at java.desktop/java.awt.Container.getMinimumSize(Container.java:1862) at java.desktop/javax.swing.JComponent.getMinimumSize(JComponent.java:1816) at java.desktop/javax.swing.BoxLayout.checkRequests(BoxLayout.java:475) at java.desktop/javax.swing.BoxLayout.minimumLayoutSize(BoxLayout.java:318) at java.desktop/java.awt.Container.minimumSize(Container.java:1878) at java.desktop/java.awt.Container.getMinimumSize(Container.java:1862) at java.desktop/javax.swing.JComponent.getMinimumSize(JComponent.java:1816) at java.desktop/javax.swing.BoxLayout.checkRequests(BoxLayout.java:475) at java.desktop/javax.swing.BoxLayout.layoutContainer(BoxLayout.java:417) at java.desktop/java.awt.Container.layout(Container.java:1541) at java.desktop/java.awt.Container.doLayout(Container.java:1530) at java.desktop/java.awt.Container.validateTree(Container.java:1725) at java.desktop/java.awt.Container.validateTree(Container.java:1734) at java.desktop/java.awt.Container.validateTree(Container.java:1734) at java.desktop/java.awt.Container.validateTree(Container.java:1734) at java.desktop/java.awt.Container.validateTree(Container.java:1734) at java.desktop/java.awt.Container.validateTree(Container.java:1734) at java.desktop/java.awt.Container.validateTree(Container.java:1734) at java.desktop/java.awt.Container.validate(Container.java:1660) at java.desktop/javax.swing.RepaintManager$3.run(RepaintManager.java:757) at java.desktop/javax.swing.RepaintManager$3.run(RepaintManager.java:755) at java.base/java.security.AccessController.doPrivileged(AccessController.java:400) at java.base/java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(ProtectionDomain.java:87) at java.desktop/javax.swing.RepaintManager.validateInvalidComponents(RepaintManager.java:754) In JList, getMinimumSize() is called from at java.desktop/javax.swing.JScrollBar.getMinimumSize(JScrollBar.java:764) at java.desktop/javax.swing.ScrollPaneLayout.minimumLayoutSize(ScrollPaneLayout.java:659) at java.desktop/java.awt.Container.minimumSize(Container.java:1878) at java.desktop/java.awt.Container.getMinimumSize(Container.java:1862) at java.desktop/javax.swing.JComponent.getMinimumSize(JComponent.java:1816) at java.desktop/javax.swing.BoxLayout.checkRequests(BoxLayout.java:475) at java.desktop/javax.swing.BoxLayout.layoutContainer(BoxLayout.java:417) at java.desktop/java.awt.Container.layout(Container.java:1541) at java.desktop/java.awt.Container.doLayout(Container.java:1530) at java.desktop/java.awt.Container.validateTree(Container.java:1725) at java.desktop/java.awt.Container.validateTree(Container.java:1734) at java.desktop/java.awt.Container.validateTree(Container.java:1734) at java.desktop/java.awt.Container.validateTree(Container.java:1734) at java.desktop/java.awt.Container.validateTree(Container.java:1734) at java.desktop/java.awt.Container.validateTree(Container.java:1734) at java.desktop/java.awt.Container.validateTree(Container.java:1734) at java.desktop/java.awt.Container.validateTree(Container.java:1734) at java.desktop/java.awt.Container.validateTree(Container.java:1734) at java.desktop/java.awt.Container.validateTree(Container.java:1734) at java.desktop/java.awt.Container.validate(Container.java:1660) at java.desktop/javax.swing.RepaintManager$3.run(RepaintManager.java:757) at java.desktop/javax.swing.RepaintManager$3.run(RepaintManager.java:755) at java.base/java.security.AccessController.doPrivileged(AccessController.java:400) at java.base/java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(ProtectionDomain.java:87) at java.desktop/javax.swing.RepaintManager.validateInvalidComponents(RepaintManager.java:754) at java.desktop/javax.swing.RepaintManager$ProcessingRunnable.run(RepaintManager.java:1896) In absence of these methods, ScrollPaneLayout.minimumLayoutSize calls JComponent.getMinimumSize [Can it cause StackOverflowError? as JComponent.getMinimumSize calls ScrollPaneLayout.minimumLayoutSize which in turn calls JComponent.getMinimumSize again so it can cause a loop for rogue app if the methods are removed] and there is no visible difference in JFileChooser or JList demos in SwingSet2 with and without these methods.
27-10-2023

I have tested with testcase JScrollBarMinLayout.java and JScrollBarMaxLayout.java testing the setting of JScrollBar preferred size with scrollbar's mininum size, maximum size with multiple L&Fs and the scrollbar looks visually same with these getMinimumSize, getMaximumSize methods and also without these methods. Attached are the screenshots of the layouts with different L&F with top one being with the methods and bottom image without the methods.
27-10-2023

A pull request was submitted for review. URL: https://git.openjdk.org/jdk/pull/15325 Date: 2023-08-17 08:42:13 +0000
17-08-2023

EVALUATION At this point it's undoubtedly the case that some folks are depending upon these implementations. As such, we can't really remove them. Instead, the implementations should check if the minimum/maximum size has been set, and if so honor it.
16-01-2007

WORK AROUND Create a subclass of JScrollBar like so: JScrollBar bar = new JScrollBar( SwingConstants.HORIZONTAL ) { public Dimension getMinimumSize() { // If setMinimumSize() was called, use Component.minimumSize(). if ( isMinimumSizeSet() ) return super.minimumSize(); // Else, fall back to the (broken) superclass implementation. return super.getMinimumSize(); } };
09-01-2007