Reputation: 134
Just as the title suggests, I am creating a custom JComboBox, and the custom BasicComboPopup does not hide when I write popup.hide(); Also if you guys know of a simpler way of making a JComboBox that shows abbreviated values in the main component, but the un-abbreviated content in the popup, I'm all ears. Here's my code:
import javax.swing.JComboBox;
import java.awt.event.MouseEvent;
import java.awt.event.MouseAdapter;
import javax.swing.JFrame;
import java.awt.GridBagLayout;
import java.awt.Component;
import java.awt.Container;
import javax.swing.JButton;
import java.awt.event.ActionListener;
import java.awt.event.ActionEvent;
import javax.swing.JPopupMenu;
import javax.swing.plaf.basic.BasicComboPopup;
class ChangingCombos extends JFrame
{
String[] abbrStr = new String[]{"--","TF","FF","SP"};
String[] longStr = new String[]{"-Select One-","Thermo Film","Fashion Film","Specialty"};
AbbreviatedComboBox<String> box = new AbbreviatedComboBox<String>(longStr,abbrStr);
public ChangingCombos()
{
setLayout(new GridBagLayout());
add(box);
setDefaultCloseOperation(EXIT_ON_CLOSE);
setLocation(300,300);
pack();
setVisible(true);
}
public static void main(String[]args)
{
new ChangingCombos();
}
class AbbreviatedComboBox<E> extends JComboBox<E>
{
E[] items = null;
E[] abbreviations = null;
BasicComboPopup popup = null;
JComboBox self = this;
JComboBox<E> abstractBox;
public AbbreviatedComboBox(E[] items, E[] abbreviations)
{
super(abbreviations);
this.items = items;
this.abbreviations = abbreviations;
abstractBox = new JComboBox<E>(items);
popup = new BasicComboPopup(abstractBox);
addCustomMouseListener(this);
for(Component c: GUIUtilities.getAllSubcomponentsOf(this))addCustomMouseListener(c);
}
private void addCustomMouseListener(Component c)
{
c.addMouseListener(new MouseAdapter()
{
public void mousePressed(MouseEvent e)
{
System.out.println("ohp");
if(!popup.isVisible())
{
popup.show(self,0,self.getHeight());
}
else popup.hide();
}
});
}
}
}
...also, to explain GUIUtilities
, it's another custom class and the method getAllSubcomponentsOf(Container c)
recursively returns all components contained within said container. It's a quick way for me to access the little arrow button on a JComboBox. It might seem like it would create an issue with adding multiple listeners to the same object, but it only iterates through the action once, as was verified with the System.out.println("ohp")
only printing once per click.
Edit: setVisible(false)
doesn't work. The hide method I refer to is ComboPopup.hide()
; it is not deprecated. When I do abstractBox.hidePopup()
, it doesn't do anything, because abstractBox
is not showing on screen, and never intended to. Just its popup. Keep trying.
Upvotes: 0
Views: 531
Reputation: 324098
a simpler way of making a JComboBox that shows abbreviated values in the main component, but the un-abbreviated content in the popup
You store a custom Object in the ComboBoxModel that contains the two properties:
Then you can use a custom renderer for the combo box to display the description value.
Check out ComboBox With Custom Renderer for more information and code examples of this approach.
You can also check out the Combo Box Prompt which allows you to prompt for a value without storing an item in the ComboBoxModel. You will need to incorporate this solution into the renderer from the above example.
Edit:
Maybe I misunderstood your requirement. Here is a simple example that renderer the dropdown list differently than the display in the combo box:
import java.awt.*;
import javax.swing.*;
import javax.swing.plaf.basic.*;
public class ComboBoxRenderer extends JPanel
{
public ComboBoxRenderer()
{
String[] items = { "Red", "Green", "Blue" };
JComboBox<String> comboBox = new JComboBox<String>( items );
comboBox.setSelectedIndex(-1);
comboBox.setPrototypeDisplayValue( "Select Color" );
comboBox.setRenderer( new MyRenderer() );
add(comboBox, BorderLayout.NORTH );
}
class MyRenderer extends BasicComboBoxRenderer
{
public Component getListCellRendererComponent(
JList list, Object value, int index, boolean isSelected, boolean cellHasFocus)
{
super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus);
if (value == null)
value = "Select Color";
if (index == -1 && value != null)
{
setText(value.toString());
}
else
setText(index + " : " + value);
return this;
}
}
private static void createAndShowGUI()
{
JFrame frame = new JFrame("SSCCE");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(new ComboBoxRenderer());
frame.setLocationByPlatform( true );
frame.pack();
frame.setVisible( true );
}
public static void main(String[] args)
{
EventQueue.invokeLater(new Runnable()
{
public void run()
{
createAndShowGUI();
}
});
}
}
Upvotes: 1
Reputation: 134
This is what I ultimately ended up using.
import javax.swing.border.LineBorder;
import java.awt.Dimension;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import javax.swing.JComboBox;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.Component;
import javax.swing.JButton;
import javax.swing.plaf.basic.BasicComboPopup;
class AbbreviatedComboBox<E> extends JComboBox<E> implements MouseListener, ItemListener
{
AbbreviatedComboBox<E> self = this;
E[] items = null;
E[] abbreviations = null;
JComboBox<E> abstractBox = null;
BasicComboPopup popup = null;
JButton comboBoxButton = null;
int maximumRowCount = 0;
public AbbreviatedComboBox(E[] items, E[] abbreviations)
{
super(abbreviations);
this.items = items;
this.abbreviations = abbreviations;
abstractBox = new JComboBox<E>(items);
new JComboBoxRowCountRetreival();
popup = new BasicComboPopup(abstractBox);
for(Component c: getComponents())if(c instanceof JButton)comboBoxButton = (JButton)c;
for(MouseListener l: getMouseListeners())removeMouseListener(l);
for(MouseListener l: comboBoxButton.getMouseListeners())comboBoxButton.removeMouseListener(l);
addMouseListener(this);
comboBoxButton.addMouseListener(this);
abstractBox.addItemListener(this);
popup.setPreferredSize(new Dimension(popup.getPreferredSize().width,popup.getPreferredSize().height/maximumRowCount*items.length+popup.getMargin().top+popup.getMargin().bottom+(((LineBorder)popup.getBorder()).getThickness()*2)));
popup.addMouseListener(this);
}
public void itemStateChanged(ItemEvent e)
{
for(int i = 0; i < items.length; i++)if(items[i].equals(e.getItem()))setSelectedIndex(i);
popup.hide();
}
public void mousePressed(MouseEvent e)
{
requestFocusInWindow();
if(!popup.isVisible())
{
popup.show(this,0,getHeight());
}
else
{
popup.hide();
}
}
public void mouseReleased(MouseEvent e){}
public void mouseClicked(MouseEvent e){}
public void mouseEntered(MouseEvent e){}
public void mouseExited(MouseEvent e){}
class JComboBoxRowCountRetreival extends JComboBox
{
public JComboBoxRowCountRetreival()
{
super();
self.maximumRowCount = super.maximumRowCount;
}
}
}
Upvotes: 0