Previously, I was able to adjusting combo box popup's width, by referring to the technique described in [http://tips4java.wordpress.com/2010/11/28/combo-box-popup/|http://tips4java.wordpress.com/2010/11/28/combo-box-popup/]. During that time, I was using 1.0.6_24-b07.
However, after I update my Java runtime to 1.0.6_26-b03, things broke.
Here is the screen shoot.
[Workable screen shoot|http://i.imgur.com/0elo7.png]
[Not workable screen shoot|http://i.imgur.com/BeKMy.png]
Here is the code snippet to demonstrate this problem.
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
/*
* NewJFrame.java
*
* Created on Aug 9, 2011, 4:13:41 AM
*/
package experiment;
import java.awt.Component;
import java.awt.Container;
import java.awt.Dimension;
import javax.swing.JComboBox;
import javax.swing.JList;
import javax.swing.JScrollBar;
import javax.swing.JScrollPane;
import javax.swing.SwingUtilities;
import javax.swing.event.PopupMenuEvent;
import javax.swing.event.PopupMenuListener;
import javax.swing.plaf.basic.BasicComboPopup;
/**
*
* @author yccheok
*/
public class NewJFrame extends javax.swing.JFrame {
/**
* Adjust popup for combo box, so that horizontal scrollbar will not display.
* 8039483
* http://www.camick.com/java/source/BoundsPopupMenuListener.java
*
* @param comboBox The combo box
*/
public static void adjustPopupWidth(JComboBox comboBox) {
if (comboBox.getItemCount() == 0) return;
Object comp = comboBox.getAccessibleContext().getAccessibleChild(0);
if (!(comp instanceof BasicComboPopup)) {
return;
}
BasicComboPopup popup = (BasicComboPopup)comp;
JList list = popup.getList();
JScrollPane scrollPane = getScrollPane(popup);
// Just to be paranoid enough.
if (list == null || scrollPane == null) {
return;
}
// Determine the maximimum width to use:
// a) determine the popup preferred width
// b) ensure width is not less than the scroll pane width
int popupWidth = list.getPreferredSize().width
+ 5 // make sure horizontal scrollbar doesn't appear
+ getScrollBarWidth(popup, scrollPane);
Dimension scrollPaneSize = scrollPane.getPreferredSize();
popupWidth = Math.max(popupWidth, scrollPaneSize.width);
// Adjust the width
scrollPaneSize.width = popupWidth;
scrollPane.setPreferredSize(scrollPaneSize);
scrollPane.setMaximumSize(scrollPaneSize);
}
/*
* I can't find any property on the scrollBar to determine if it will be
* displayed or not so use brute force to determine this.
*/
private static int getScrollBarWidth(BasicComboPopup popup, JScrollPane scrollPane) {
int scrollBarWidth = 0;
Component component = popup.getInvoker();
if (component instanceof JComboBox) {
JComboBox comboBox = (JComboBox)component;
if (comboBox.getItemCount() > comboBox.getMaximumRowCount()) {
JScrollBar vertical = scrollPane.getVerticalScrollBar();
scrollBarWidth = vertical.getPreferredSize().width;
}
}
return scrollBarWidth;
}
/*
* Get the scroll pane used by the popup so its bounds can be adjusted
*/
private static JScrollPane getScrollPane(BasicComboPopup popup) {
JList list = popup.getList();
Container c = SwingUtilities.getAncestorOfClass(JScrollPane.class, list);
return (JScrollPane)c;
}
/** Creates new form NewJFrame */
public NewJFrame() {
initComponents();
this.jComboBox1.addPopupMenuListener(getPopupMenuListener());
}
/** This method is called from within the constructor to
* initialize the form.
* WARNING: Do NOT modify this code. The content of this method is
* always regenerated by the Form Editor.
*/
@SuppressWarnings("unchecked")
// <editor-fold defaultstate="collapsed" desc="Generated Code">
private void initComponents() {
jComboBox1 = new javax.swing.JComboBox();
setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);
jComboBox1.setModel(new javax.swing.DefaultComboBoxModel(new String[] { "Item 1", "Item 2", "Item 3", "Item 4", "This is a very long text. This is a very long text" }));
javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
getContentPane().setLayout(layout);
layout.setHorizontalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
.addGap(82, 82, 82)
.addComponent(jComboBox1, javax.swing.GroupLayout.PREFERRED_SIZE, 76, javax.swing.GroupLayout.PREFERRED_SIZE)
.addContainerGap(242, Short.MAX_VALUE))
);
layout.setVerticalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
.addGap(34, 34, 34)
.addComponent(jComboBox1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addContainerGap(246, Short.MAX_VALUE))
);
pack();
}// </editor-fold>
/**
* @param args the command line arguments
*/
public static void main(String args[]) {
java.awt.EventQueue.invokeLater(new Runnable() {
public void run() {
new NewJFrame().setVisible(true);
}
});
}
private PopupMenuListener getPopupMenuListener() {
return new PopupMenuListener() {
@Override
public void popupMenuWillBecomeVisible(PopupMenuEvent e) {
// We will have a much wider drop down list.
adjustPopupWidth(jComboBox1);
}
@Override
public void popupMenuWillBecomeInvisible(PopupMenuEvent e) {
}
@Override
public void popupMenuCanceled(PopupMenuEvent e) {
}
};
}
// Variables declaration - do not modify
private javax.swing.JComboBox jComboBox1;
// End of variables declaration
}