JComboBox not showing arrow
Asked Answered
H

4

5

I have been searching this site and google for a solution to my problem, and I can't find anything. I think it's supposed to just work; however, it doesn't. The arrow icon for my JComboBox doesn't show up, and I can't find anywhere to set its visibility to true.

Here's my code:

public class Driver implements ActionListener {

private JTextField userIDField;
private JTextField[] documentIDField;
private JComboBox repository, environment;
private JButton close, clear, submit;
private JFrame window;

    public Driver()
    {
    window = makeWindow();
    makeContents(window);
    window.repaint();
    }

    private JFrame makeWindow()
    {
    JFrame window = new JFrame("");
    window.setSize(500,300);
    window.setLocation(50,50);
    window.getContentPane().setLayout(null);
    window.setResizable(false);
    window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    window.setVisible(true);

    return window;
    }

    private void makeContents(JFrame w)
    {
    makeDropDowns(w);
    w.repaint();
    }

    private void makeDropDowns(JFrame w)
    {       
    String[] repositoryArray = {"Click to select", "NSA", "Finance", "Test"};
    repository = new JComboBox(repositoryArray);
    repository.setSelectedIndex(0);
    repository.addActionListener(this);
    repository.setSize(150,20);
    repository.setLocation(175,165);
    repository.setEditable(false);
    w.add(repository);

    String[] environmentArray = {"Click to select", "Dev", "Test", "Qual"};
    environment = new JComboBox(environmentArray);
    environment.setSelectedIndex(0);
    environment.addActionListener(this);
    environment.setSize(150,20);
    environment.setLocation(175,195);
    //environment.setEditable(false);
    w.add(environment,0);
}

    public void actionPerformed(ActionEvent e) 
    {

    String repositoryID = "null", environmentID = "null";

    if (e.getSource() == repository)
        {
        repositoryID = (String)repository.getSelectedItem();
        }

    if(e.getSource() == environment)
        {
        environmentID = (String)environment.getSelectedItem();
        }
    }
}

Here's a link to a picture of the problem:

image

If anyone could help that would be awesome.

Hardpan answered 30/5, 2012 at 20:50 Comment(3)
What environment / L&F are you using? Can you show an image of what is showing? Also, bear in mind for a JComboBox, the button is not really required - the whole JComboBox sort of works like a button.Tincal
I was able to run your example fine; the combo box shows up and has a dropdown arrow next to it. I believe the presence/absence of a button will depend on the LnF, so you might experience different behavior on windows/OSX/unix etc...Tankard
1) Is "Click to select" a valid option? If not, it should not be listed in the combo. 2) environment.setSize(150,20); Don't do that. 3) environment.setLocation(175,195); Don't do that either. 4) w.add(environment,0); Do use meaningful attribute names. Don't use magic numbers. 4) For better help sooner, post an SSCCE.Nugget
R
11

It doesn't appear to be the issue you were suffering from, but I found this post due to the same resulting issue of the arrow disappearing.

In my case it was due to me mistakenly using .removeAll() on the JComboBox rather than .removeAllItems() when I was attempting to empty and then reuse the JComboBox after a refresh of the data I was using. Just thought I'd include it as an answer in case someone else comes across this thread for similar reasons.

Revkah answered 6/1, 2015 at 23:14 Comment(1)
Old answer to an old question, but it just saved me a lot of confusion! Thanks :)Modesta
R
5

The code you show works, but it looks like you're fighting the enclosing container's default layout. Here, ComboTest is a JPanel which defaults to FlowLayout.

Addendum: In general, do not use absolute positioning, as shown in your update. I've changed the example to use GridLayout; comment out the setLayout() call to see the default, FlowLayout.

enter image description here

import java.awt.EventQueue;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JComboBox;
import javax.swing.JFrame;
import javax.swing.JPanel;

/**
* @see https://mcmap.net/q/1870450/-jcombobox-not-showing-arrow
*/
public class ComboTest extends JPanel {

    private JComboBox repository = createCombo(new String[]{
        "Click to select", "NSA", "Finance", "Test"});
    private JComboBox environment = createCombo(new String[]{
        "Click to select", "Dev", "Test", "Qual"});

    public ComboTest() {
        this.setLayout(new GridLayout(0, 1));
        this.add(repository);
        this.add(environment);
    }

    private JComboBox createCombo(String[] data) {
        final JComboBox combo = new JComboBox(data);
        combo.setSelectedIndex(1);
        combo.addActionListener(new ActionListener() {

            @Override
            public void actionPerformed(ActionEvent e) {
                System.out.println(e.getActionCommand()
                    + ": " + combo.getSelectedItem().toString());
            }
        });
        return combo;
    }

    private void display() {
        JFrame f = new JFrame("ComboTest");
        f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        f.add(this);
        f.pack();
        f.setLocationRelativeTo(null);
        f.setVisible(true);
    }

    public static void main(String[] args) {
        EventQueue.invokeLater(new Runnable() {

            @Override
            public void run() {
                new ComboTest().display();
            }
        });
    }
}
Responsion answered 30/5, 2012 at 21:26 Comment(7)
This is part of a form that I'm having people fill out with a bunch of other things (JLabels, JTextFields, etc) that are all in a JFrame. I have tried setting up a JPanel and puting it in the location I need it to be, but it still didn't have the little arrow. I have also tried setting the layout of environment to the FlowLayout. This didn't change anything either. Any more help would be greatly appreciated.Hardpan
The result depends on the layout of the enclosing container. Try adding components to the example above and see how FlowLayout responds. Then try setLayout(new GridLayout(0, 1))) for comparison.Responsion
Yeah, it seems your example works just fine; however, when I try to implement it into my code it doesn't run at all. (As in, I made your class a class in my project, and made new variables with your constructor). Nothing showed up. When I use just your code in its own project it works fine. Is there an easy way I can just force the use of the FlowLayout within either the JFrame i'm using, or the JComboBox?Hardpan
Yes, nest the ComboTest panel in your application's panel. I suspect you are mixing Absolute Positioning with the default layout. Please edit your question to include an sscce that exhibits the problem.Responsion
Alrighty, I have removed pretty much everything that isn't required to see my problem. The drop down menus are in the correct place, but still show that they don't have the down arrow. :(Hardpan
I have updated my post with a link to a screenshot of the problem.Hardpan
Your example is incomplete; after fixing it, I was unable to reproduce your finding. I encourage you to use layouts correctly, as I have shown.Responsion
G
2

I had the same issue. I fixed it by revalidating and repainting the panel with the following code :

myPanel.revalidate();
myPanel.repaint();
Grace answered 6/9, 2014 at 22:41 Comment(1)
Had the same issue. frame.revalidate() and frame.repaint() worked for me.Messuage
P
1

Maybe a little late, but for those who are still looking for an easy and fail-safe way to use the JComboBox can use this:

public class FixedJComboBox<E>
        extends JComboBox<E> {
    // Copied constructors
    public FixedJComboBox() {
        super();
    }
    public FixedJComboBox(ComboBoxModel<E> aModel) {
        super(aModel);
    }
    public FixedJComboBox(E[] items) {
        super(items);
    }
    public FixedJComboBox(Vector<E> items) {
        super(items);
    }

    @Override
    public void setBounds(int x, int y, int width, int height) {
        super.setBounds(x, y, width, height);

        // The arrow is the first (and only) component
        // that is added by default
        Component[] comps = getComponents();
        if (comps != null && comps.length >= 1) {
            Component arrow = comps[0];
            // 20 is the default width of the arrow (for me at least)
            arrow.setSize(20, height);
            arrow.setLocation(width - arrow.getWidth(), 0);
        }
    }
}

As described here, the bug is caused by incorrectly setting both the location and the size of the arrow to (0,0), followed by some repainting issues. By simply overriding the setBounds() function, the arrow is always corrected after the UI/layout manager has wrongly updated the arrow.

Also, since new components are added after the old ones (i.e. higher index), the arrow will always be at the first element in the array (assuming you don't remove and re-add the arrow).

The disadvantage is of this class is that the width of the arrow is now determined by a constant instead of the UI/layout manager.

Polymerize answered 15/8, 2018 at 21:52 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.