Drop Down Buttons in Swing: A New Alternative
The best survey I have found on the status of Drop Down Buttons in Swing is The Ubiquitous Drop Down Button - Swing Style, on the Mammoth Software site. The author discusses the approach taken by Santhosh Kumar and another approach taken by the PSP (Personal Software Process) Dashboard. Problems across look and feels are identified and the consequences of extending the Box class instead of the JButton class are highlighted, among other areas. Then the Mammoth Software Drop Down Button is presented, requiring a certain amount of coding, because the solution is built from the ground up, which also has its advantages, such as the fact that you have a lot more control than if you were using someone's library.
However, let's look at a different approach. Irrespective of the question of which one is better/worse, it's at least useful knowing that this one is out there too. A NetBeans API changes log dating from May 4, 2007, says the following, in its typical lowkey tone of voice: "Added a factory class that can create special buttons with a small arrow icon that brings up a popup menu when clicked."
At least an exclamation mark would have been justified! Here, before I show the code, is the result in a simple sample application:

That's what one would expect a Drop Down Button to do, right? Well, there it is. In fact, it is one of the very many hidden features of the NetBeans Platform. But you can forget the NetBeans Platform (as well as NetBeans IDE). Both of these are irrelevant to this story, neither are needed, just one single JAR file from the NetBeans IDE distribution. In the same way as you can reuse the NetBeans Visual Library API in your own Java applications (i.e., outside of the NetBeans Platform), you can also take the NetBeans UI Utilities API (platform7/modules/org-openide-awt.jar in any distribution of NetBeans IDE) and simply make it available to your own application.
Once you've done that, life is good, you can use the org.openide.awt.DropDownButtonFactory class:
//declarations:
private static JButton dropDownButton;
private static JPopupMenu popup;
private MyMenuItemListener menuItemListener;
...
...
...
//constructor:
public DemoJFrame() {
//create JFrame, add JMenuBar,
//together with some JMenus and JMenuItems:
initComponents();
//initialize JPopupMenu:
popup = new JPopupMenu();
//initialize ActionListener:
menuItemListener = new MyMenuItemListener();
//declare array of names:
String[] names = {"John", "Paul", "Ringo", "George"};
//iterate through the names,
//create JMenuItem from each,
//set name and add ActionListener,
//and then add to JPopupMenu:
for (int i = 0; i < names.length; i++) {
String name = names[i];
JMenuItem item = new JMenuItem(name);
item.setName(name);
item.addActionListener(menuItemListener);
popup.add(item);
}
//use the org.openide.awt.DropDownButtonFactory to create a DropDownButton,
//define the icon and then assign our JPopupMenu to the JButton:
dropDownButton = DropDownButtonFactory.createDropDownButton(
new ImageIcon(new BufferedImage(16, 16, BufferedImage.TYPE_INT_ARGB)),
popup);
//the JButton will be quite long by default,
//let's trim it by removing borders:
dropDownButton.setBorder(javax.swing.BorderFactory.
createEmptyBorder(1, 1, 1, 1));
//set the icon:
dropDownButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/demo/copy.gif")));
//add the JButton to the menu bar:
mainMenuBar.add(dropDownButton);
}
...
...
...
I am curious to know what other Swing developers think of this solution. One thing I need to do is show the result under different look and feels, as the article mentioned in the introduction did. Other than that, it's great how this solution integrates so closely with existing JButtons and JMenuItems and simply repurposes them so effectively.





Comments
Richard Osbaldeston replied on Wed, 2008/03/05 - 10:02am
Why create the button via the factory with an empty ImageIcon and then later set the Icon manually? Were you just showing it could be done? The other thing that strikes me is the use of a factory, is that nessecary? While I like ComponentFactories myself they don't play nice with GUI builders. Having Netbeans components that can't be used as beans in the Netbeans Pallete seems like shooting yourself in the foot. Why don't they publish a library for the pallette if they'd like more people using them?
Don't understand this step myself (I still import from jars) but I know the swingx guys have been trying to achive this with builds after 0.9.2. Not that Netbeans always plays nice with SwingX either because of the classloader behviour conflicting with SwingXs ComponentAddons ref: http://www.netbeans.org/issues/show_bug.cgi?id=127881 .
Oh, and theres a couple of DropButtons in the swingx incubator too.. Theres a DropButton and a SplitButton hidden in there somewhere. Split works a little differently though, the button is divided into two distinct actions one for the arrow (shows dropdown) and one for the button action (button type selected from drop down). Works like the PhotoShop palette tools.
Geertjan Wielenga replied on Wed, 2008/03/05 - 10:07am
Kirill Grouchnikov replied on Wed, 2008/03/05 - 11:37am
Patrick Gotthardt replied on Wed, 2008/03/05 - 11:56am
Jidesoft also offers a free split button component (its part of our jide-common project at java.net). Well tested, heavily used. Certainly not a bad idea to use that one.
Adding the feature from the outside isn't a bad idea though. I have published a blog entry about this (using a custom border for the arrow icon) a couple of years ago and used the same approach to develop a JTextField with icons/dropdown capabilities. But still, I'd suggest using Jides (not just because I work for them, but also because it's well tested and supported).
Andres Almiray replied on Wed, 2008/03/05 - 1:42pm
in response to:
Patrick Gotthardt
Fabrizio Giudici replied on Wed, 2008/03/05 - 1:55pm
Desmond Kirrane replied on Fri, 2009/06/19 - 7:49am
Hi Geertjan,
Just found this GREAT post! and need some help.
I am creating a NetBeans Plugin and would like to use this button. My problem is: How can I add this to my existing GUI that was created with The GUI Builder (Matisse). I can't edit the code as itr was generated by the GUI Builder.
Is there a way to add this to the Matisse Palette in NetBeans?
Desmond Kirrane replied on Fri, 2009/06/19 - 8:01am
By the way. What NetBeans IDE class is used to create the other buttons in the GUI you have shown e.g the scissors button.
prasad de zoysa replied on Fri, 2009/07/31 - 1:24am
hello sir,
can you send me a complete sample code please... i need in immediatly..
prasaddev.
Ram Venkat replied on Mon, 2010/02/22 - 1:24am