There's a class called https://tips4java.wordpress.com/2010/11/28/combo-box-popup/ , which can control the size of the popup that opens from the combo options, according to the larger item.After some adjustments, I managed to make that by changing an item in the combo, it was resized to the size of the item.Just add the class BoundsPopupMenuListener in your project and configure it as a combo popup listener, as follows in the executable example below:import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class ComboResizing {
public void createAndShowGUI() {
final JFrame frame = new JFrame();
frame.setTitle("Frame Teste");
frame.setPreferredSize(new Dimension(300, 200));
frame.setLayout(new FlowLayout(FlowLayout.CENTER));
String[] tabs = {"txt short", "text more longer", "text more more longer"};
JComboBox combo = new JComboBox(tabs);
combo.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
//este método redefine o tamanho preferido
//do combo baseado num valor prototipo
//passado como parametro, neste caso
//o item selecionado
combo.setPrototypeDisplayValue(combo.getSelectedItem());
//força o frame a ser redesenhado
frame.pack();
}
});
//classe que define o tamanho do popup do combo
//conforme o tamanho do valor prototipo
//e redimensiona se houver itens muito grande
BoundsPopupMenuListener listener = new BoundsPopupMenuListener(true, false);
combo.addPopupMenuListener(listener);
combo.setPrototypeDisplayValue(combo.getSelectedItem());
frame.add(combo);
frame.pack();
frame.setVisible(true);
frame.setLocationRelativeTo(null);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
new ComboResizing().createAndShowGUI();
}
});
}
}
The relevant sections are those with explanatory comments.The result of this example would be like this: Class code BoundsPopupMenuListener is available in the link at the end of the response, but I will copy it here to facilitate the query if the link is unavailable:import java.awt.;
import javax.swing.;
import javax.swing.event.;
import javax.swing.plaf.basic.;
/**
This class will change the bounds of the JComboBox popup menu to support
different functionality. It will support the following features: - a
horizontal scrollbar can be displayed when necessary - the popup can be wider
than the combo box - the popup can be displayed above the combo box
Class will only work for a JComboBox that uses a BasicComboPop.
*/
public class BoundsPopupMenuListener implements PopupMenuListener {
private boolean scrollBarRequired = true;
private boolean popupWider;
private int maximumWidth = -1;
private boolean popupAbove;
private JScrollPane scrollPane;
/**
Convenience constructore to allow the display of a horizontal scrollbar
when required.
*/
public BoundsPopupMenuListener() {
this(true, false, -1, false);
}
/**
Convenience constructor that allows you to display the popup wider and/or
above the combo box.
@param popupWider when true, popup width is based on the popup preferred
width
@param popupAbove when true, popup is displayed above the combobox
*/
public BoundsPopupMenuListener(boolean popupWider, boolean popupAbove) {
this(true, popupWider, -1, popupAbove);
}
/**
Convenience constructor that allows you to display the popup wider than
the combo box and to specify the maximum width
@param maximumWidth the maximum width of the popup. The popupAbove value
is set to "true".
*/
public BoundsPopupMenuListener(int maximumWidth) {
this(true, true, maximumWidth, false);
}
/**
General purpose constructor to set all popup properties at once.
@param scrollBarRequired display a horizontal scrollbar when the
preferred width of popup is greater than width of scrollPane.
@param popupWider display the popup at its preferred with
@param maximumWidth limit the popup width to the value specified (minimum
size will be the width of the combo box)
@param popupAbove display the popup above the combo box
*/
public BoundsPopupMenuListener(
boolean scrollBarRequired, boolean popupWider, int maximumWidth, boolean popupAbove) {
setScrollBarRequired(scrollBarRequired);
setPopupWider(popupWider);
setMaximumWidth(maximumWidth);
setPopupAbove(popupAbove);
}
/**
Return the maximum width of the popup.
@return the maximumWidth value
*/
public int getMaximumWidth() {
return maximumWidth;
}
/**
Set the maximum width for the popup. This value is only used when
setPopupWider( true ) has been specified. A value of -1 indicates that
there is no maximum.
@param maximumWidth the maximum width of the popup
*/
public void setMaximumWidth(int maximumWidth) {
this.maximumWidth = maximumWidth;
}
/**
Determine if the popup should be displayed above the combo box.
@return the popupAbove value
*/
public boolean isPopupAbove() {
return popupAbove;
}
/**
Change the location of the popup relative to the combo box.
@param popupAbove true display popup above the combo box, false display
popup below the combo box.
*/
public void setPopupAbove(boolean popupAbove) {
this.popupAbove = popupAbove;
}
/**
Determine if the popup might be displayed wider than the combo box
@return the popupWider value
*/
public boolean isPopupWider() {
return popupWider;
}
/**
Change the width of the popup to be the greater of the width of the combo
box or the preferred width of the popup. Normally the popup width is
always the same size as the combo box width.
@param popupWider true adjust the width as required.
*/
public void setPopupWider(boolean popupWider) {
this.popupWider = popupWider;
}
/**
Determine if the horizontal scroll bar might be required for the popup
@return the scrollBarRequired value
*/
public boolean isScrollBarRequired() {
return scrollBarRequired;
}
/**
For some reason the default implementation of the popup removes the
horizontal scrollBar from the popup scroll pane which can result in the
truncation of the rendered items in the popop. Adding a scrollBar back to
the scrollPane will allow horizontal scrolling if necessary.
@param scrollBarRequired true add horizontal scrollBar to scrollPane
false remove the horizontal scrollBar
*/
public void setScrollBarRequired(boolean scrollBarRequired) {
this.scrollBarRequired = scrollBarRequired;
}
/**
Alter the bounds of the popup just before it is made visible.
*/
@Override
public void popupMenuWillBecomeVisible(PopupMenuEvent e) {
JComboBox comboBox = (JComboBox) e.getSource();
if (comboBox.getItemCount() == 0) {
return;
}
final Object child = comboBox.getAccessibleContext().getAccessibleChild(0);
if (child instanceof BasicComboPopup) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
customizePopup((BasicComboPopup) child);
}
});
}
}
protected void customizePopup(BasicComboPopup popup) {
scrollPane = getScrollPane(popup);
if (popupWider) {
popupWider(popup);
}
checkHorizontalScrollBar(popup);
// For some reason in JDK7 the popup will not display at its preferred
// width unless its location has been changed from its default
// (ie. for normal "pop down" shift the popup and reset)
Component comboBox = popup.getInvoker();
Point location = comboBox.getLocationOnScreen();
if (popupAbove) {
int height = popup.getPreferredSize().height;
popup.setLocation(location.x, location.y - height);
} else {
int height = comboBox.getPreferredSize().height;
popup.setLocation(location.x, location.y + height - 1);
popup.setLocation(location.x, location.y + height);
}
}
/*
Adjust the width of the scrollpane used by the popup
*/
protected void popupWider(BasicComboPopup popup) {
JList list = popup.getList();
// Determine the maximimum width to use:
// a) determine the popup preferred width
// b) limit width to the maximum if specified
// c) 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);
if (maximumWidth != -1) {
popupWidth = Math.min(popupWidth, maximumWidth);
}
Dimension scrollPaneSize = scrollPane.getPreferredSize();
popupWidth = Math.max(popupWidth, scrollPaneSize.width);
// Adjust the width
scrollPaneSize.width = popupWidth;
scrollPane.setPreferredSize(scrollPaneSize);
scrollPane.setMaximumSize(scrollPaneSize);
}
/*
This method is called every time:
to make sure the viewport is returned to its default position
to remove the horizontal scrollbar when it is not wanted
*/
private void checkHorizontalScrollBar(BasicComboPopup popup) {
// Reset the viewport to the left
JViewport viewport = scrollPane.getViewport();
Point p = viewport.getViewPosition();
p.x = 0;
viewport.setViewPosition(p);
// Remove the scrollbar so it is never painted
if (!scrollBarRequired) {
scrollPane.setHorizontalScrollBar(null);
return;
}
// Make sure a horizontal scrollbar exists in the scrollpane
JScrollBar horizontal = scrollPane.getHorizontalScrollBar();
if (horizontal == null) {
horizontal = new JScrollBar(JScrollBar.HORIZONTAL);
scrollPane.setHorizontalScrollBar(horizontal);
scrollPane.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED);
}
// Potentially increase height of scroll pane to display the scrollbar
if (horizontalScrollBarWillBeVisible(popup, scrollPane)) {
Dimension scrollPaneSize = scrollPane.getPreferredSize();
scrollPaneSize.height += horizontal.getPreferredSize().height;
scrollPane.setPreferredSize(scrollPaneSize);
scrollPane.setMaximumSize(scrollPaneSize);
scrollPane.revalidate();
}
}
/*
Get the scroll pane used by the popup so its bounds can be adjusted
*/
protected JScrollPane getScrollPane(BasicComboPopup popup) {
JList list = popup.getList();
Container c = SwingUtilities.getAncestorOfClass(JScrollPane.class, list);
return (JScrollPane) c;
}
/*
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.
*/
protected int getScrollBarWidth(BasicComboPopup popup, JScrollPane scrollPane) {
int scrollBarWidth = 0;
JComboBox comboBox = (JComboBox) popup.getInvoker();
if (comboBox.getItemCount() > comboBox.getMaximumRowCount()) {
JScrollBar vertical = scrollPane.getVerticalScrollBar();
scrollBarWidth = vertical.getPreferredSize().width;
}
return scrollBarWidth;
}
/*
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.
*/
protected boolean horizontalScrollBarWillBeVisible(BasicComboPopup popup, JScrollPane scrollPane) {
JList list = popup.getList();
int scrollBarWidth = getScrollBarWidth(popup, scrollPane);
int popupWidth = list.getPreferredSize().width + scrollBarWidth;
return popupWidth > scrollPane.getPreferredSize().width;
}
@Override
public void popupMenuCanceled(PopupMenuEvent e) {
}
@Override
public void popupMenuWillBecomeInvisible(PopupMenuEvent e) {
// In its normal state the scrollpane does not have a scrollbar
if (scrollPane != null) {
scrollPane.setHorizontalScrollBar(null);
}
}
}
References: https://stackoverflow.com/questions/8679421/why-jcombobox-ignore-prototypedisplayvalue https://stackoverflow.com/q/8679421/5524514