I want to remove the editor from a JComboBox to make the arrow button span the entire width of the box.
I tried to use a custom ComboBoxUI to set the size and color of the arrow button. This partially works, but because i couldn't figure out how to remove the editor, the button is only half the width of the entire box.
The main class:
import javax.swing.*;
import java.awt.*;
public class Box {
public Box() {
JFrame frame = new JFrame("frame");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(400,250);
JPanel panel = new JPanel();
panel.setLayout(null);
frame.add(panel);
String[] items = { "", "item1", "item2", "item3", "item4" };
JComboBox<String> box = new JComboBox<>(items);
box.setBounds(100,20,200,50);
UIManager.put("ComboBox.squareButton", Boolean.FALSE);
box.setUI(new ComboUI());
box.setBorder(BorderFactory.createMatteBorder(2,2,2,2, Color.BLACK));
panel.add(box);
frame.setVisible(true);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
public static void main(String[] args) {
new Box();
}
}
And the custom ComboBoxUI:
import javax.swing.*;
import javax.swing.plaf.basic.BasicComboBoxUI;
import java.awt.*;
public class ComboUI extends BasicComboBoxUI {
@Override
protected JButton createArrowButton() {
final JButton button = new JButton("Items");
button.setBackground(Color.GRAY);
button.setForeground(Color.WHITE);
button.setBounds(0,0, 200,40);
return button;
}
}
This code results in this:
Arrow button half the size of combo box"
What i would like instead is this:
Arrow button same size as combo box:
I created the following GUI using a JButton
and a Popup
from the PopupFactory
.
There's a JLabel
at the top to show the selection and a JButton
to show the item options. Unfortunately, I couldn't print the GUI when the item list is displayed.
When you left-click the JButton
, the list of items appear under the JButton
. When you select an item, the list disappears and the selected item is displayed.
This is a proof of concept. You would need to add code to hide the list when the Esc key is pressed to cancel the list, as one example.
Here's the complete runnable code.
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.Point;
import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JList;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.ListSelectionModel;
import javax.swing.Popup;
import javax.swing.PopupFactory;
import javax.swing.SwingUtilities;
public class ItemSelectorExample implements Runnable {
public static void main(String[] args) {
SwingUtilities.invokeLater(new ItemSelectorExample());
}
private int margin;
private JButton button;
private JFrame frame;
private JLabel label;
private JPanel buttonPanel;
private Popup popup;
@Override
public void run() {
this.margin = 5;
frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.buttonPanel = createButtonPanel();
frame.add(buttonPanel, BorderLayout.CENTER);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
private JPanel createButtonPanel() {
JPanel panel = new JPanel(new BorderLayout());
panel.setBorder(BorderFactory.createEmptyBorder(margin, margin, margin,
margin));
label = new JLabel(" ");
panel.add(label, BorderLayout.NORTH);
button = new JButton("Items");
button.addActionListener(event -> {
popup = createItemSelectionPanel();
popup.show();
});
panel.add(button, BorderLayout.CENTER);
return panel;
}
private Popup createItemSelectionPanel() {
JPanel panel = new JPanel(new FlowLayout());
panel.setBorder(BorderFactory.createEmptyBorder(margin, margin, margin,
margin));
String[] items = new String[9];
for (int index = 0; index < items.length; index++) {
items[index] = "Item " + (index + 1);
}
JList<String> list = new JList<>(items);
list.setVisibleRowCount(4);
list.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
list.addListSelectionListener(event -> {
String item = (String) list.getSelectedValue();
label.setText(item);
popup.hide();
});
JScrollPane scrollPane = new JScrollPane(list);
Dimension sp = scrollPane.getPreferredSize();
Dimension bp = buttonPanel.getSize();
Dimension b = button.getPreferredSize();
Point s = button.getLocationOnScreen();
int width = bp.width - margin - margin;
scrollPane.setPreferredSize(new Dimension(width, sp.height));
PopupFactory factory = PopupFactory.getSharedInstance();
Popup popup = factory.getPopup(panel, scrollPane, s.x, s.y + b.height);
return popup;
}
}