@@ -62,21 +62,10 @@ public CMComboBoxCellEditor(JComboBox<?> comboBox) {
6262 comboBox .addPopupMenuListener (new PopupMenuListener () {
6363 @ Override
6464 public void popupMenuWillBecomeVisible (PopupMenuEvent e ) {
65- // First call: sets popup.preferredSize so the popup *window* is created at the
66- // correct width (window size is determined from popup.preferredSize before show()).
67- adjustPopupWidth ();
68- // Second call via invokeLater: BasicComboPopup.show() calls getPopupLocation()
69- // *after* firing this listener, which re-constrains scroller.maxSize back to the
70- // column width. Running again on the next EDT cycle fixes the scroller, then
71- // revalidate/repaint forces the layout to update inside the already-wide window.
72- SwingUtilities .invokeLater (() -> {
73- adjustPopupWidth ();
74- Object child = comboBox .getUI ().getAccessibleChild (comboBox , 0 );
75- if (child instanceof JPopupMenu popup ) {
76- popup .revalidate ();
77- popup .repaint ();
78- }
79- });
65+ // BasicComboPopup.show() calls getPopupLocation() after this listener fires,
66+ // constraining the popup to the column width. Adjust on the next EDT cycle —
67+ // invokeLater lands ahead of the first WM_PAINT, so no flash occurs.
68+ SwingUtilities .invokeLater (() -> adjustPopupWidth ());
8069 }
8170 @ Override public void popupMenuWillBecomeInvisible (PopupMenuEvent e ) {}
8271 @ Override public void popupMenuCanceled (PopupMenuEvent e ) {}
@@ -97,30 +86,42 @@ public Component getTableCellEditorComponent(JTable table, Object value,
9786
9887 private void adjustPopupWidth () {
9988 Object child = comboBox .getUI ().getAccessibleChild (comboBox , 0 );
100- if (!(child instanceof JPopupMenu )) {
89+ if (!(child instanceof JPopupMenu popup )) {
10190 return ;
10291 }
103- JPopupMenu popup = (JPopupMenu ) child ;
10492 JScrollPane scrollPane = findScrollPane (popup );
10593 if (scrollPane == null ) {
10694 return ;
10795 }
96+ Window window = SwingUtilities .getWindowAncestor (popup );
97+ if (window == null ) {
98+ return ;
99+ }
108100
109- // BasicComboPopup.show() constrains the scroll pane's preferredSize and maximumSize
110- // to the column width before firing this listener. Reset them so the scroll pane
111- // reports its natural content-based width — which already incorporates item metrics,
112- // list insets, scrollbar width, and scroll pane borders — no manual overhead needed.
101+ // Clear sizes set by BasicComboPopup.getPopupLocation() so the scroll pane
102+ // reports its natural content-based width.
113103 scrollPane .setPreferredSize (null );
114104 scrollPane .setMaximumSize (null );
115105 popup .setPreferredSize (null );
116106
117107 int naturalWidth = scrollPane .getPreferredSize ().width ;
118108 int targetWidth = Math .min (Math .max (naturalWidth , comboBox .getWidth ()), ComboBoxPopup .MAX_WIDTH );
119109
120- Dimension scrollSize = new Dimension (targetWidth , scrollPane .getPreferredSize ().height );
110+ // Use the window's actual height — correctly determined by BasicComboPopup based on row count.
111+ // Setting scroller maxSize to windowHeight lets BoxLayout fill all available vertical space.
112+ int windowHeight = window .getHeight ();
113+ Dimension scrollSize = new Dimension (targetWidth , windowHeight );
121114 scrollPane .setPreferredSize (scrollSize );
122115 scrollPane .setMaximumSize (scrollSize );
123- popup .setPreferredSize (new Dimension (targetWidth , popup .getPreferredSize ().height ));
116+ popup .setPreferredSize (new Dimension (targetWidth , windowHeight ));
117+
118+ // Widen the popup window; the height was already set correctly by BasicComboPopup.
119+ Point loc = window .getLocation ();
120+ window .setSize (targetWidth , windowHeight );
121+ window .setLocation (loc );
122+
123+ popup .revalidate ();
124+ popup .repaint ();
124125 }
125126
126127 private static JScrollPane findScrollPane (Container container ) {
0 commit comments