views:

82

answers:

3

I'm scratching my head over this one. Below is a running sample. I have 2 Swing Lists in a flow layout each with a simple data model. Depending on how I instantiate the FlowLayout the 2nd List does not display its elements. Weird.

import javax.swing.*;
import java.awt.*;

public class ListboxTest2 {

    public static void main(String[] args) {

        JFrame f = new JFrame();
        f.setSize(500, 500);
        f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        JPanel panel = new JPanel();
        // this works
        // panel.setLayout(new FlowLayout(FlowLayout.LEFT, 10, 10));

        // this doesn't
        panel.setLayout(new FlowLayout());

        final JList list1 = new JList();
        list1.setPreferredSize(new Dimension(120, 60));
        final JList list2 = new JList();
        list2.setPreferredSize(new Dimension(120, 60));  

        final String[] strings1 = {"Item 1", "Item 2", "Item 3", "Item 4", "Item 5", "Item 6", "Item 7", "Item 8", "Item 9", "Item 10", "Item 11", "Item 12"};
        final String[] strings2 = {"Item 1", "Item 2", "Item 3", "Item 4", "Item 5", "Item 6", "Item 7", "Item 8", "Item 9", "Item 10", "Item 11", "Item 12"};

        list1.setModel(new AbstractListModel() {

            public int getSize() {
                return strings1.length;
            }

            public Object getElementAt(int index) {
                return strings1[index];
            }
        });
        panel.add(list1);

        list2.setModel(new AbstractListModel() {

            public int getSize() {
                return strings2.length;
            }

            public Object getElementAt(int index) {
                return strings2[index];
            }
        });
        panel.add(list2);

        f.add(panel);

        f.setVisible(true);
        list1.grabFocus();
        list1.setSelectedIndex(0);
    }

}
+2  A: 

in the first attempt, the second list only displayed one element. in all subsequent attempts, it displayed it correctly. strange.

I would try to move setVisible(true) after the rest of the initialization.

Omry
Good. I'm not going insane. Good to know.
Dan Howard
It seems:list1.grabFocus();Is SOMETIMES the culprit. But I have know idea why. Actually, try running once or twice without changing anything.
Dan Howard
+2  A: 

It is always a good practice to wrap listboxes within a JScrollPane as it would allow you to scroll when items exceed the visible area. Add the list boxes to panel like this.

panel.add(new JScrollPane(list1));
panel.add(new JScrollPane(list2));
Chandru
Yeah I might do that. In my case this is a game where I have fixed space.
Dan Howard
+2  A: 

This has nothing to do with the layout manager. You need to call pack() on the JFrame before you make it visible, otherwise the behaviour is somewhat random because you have a race condition between your main thread and the EDT.

Theoretically, all manipulation of the UI must happen in the EDT, including the original setup. In practice, you can avoid this by doing the setup completely before the EDT starts (which I believe usually happens when the first component is made visible). I suspect that in your code, the grabFocus() causes the layout of the UI to be computed on the main thread, which then results in a race condition with the EDT started by setVisible().

Michael Borgwardt
This works! Except with the lines:list1.grabFocus();list1.setSelectedIndex(0);Then list2 is still messed up.
Dan Howard
@Dan: you may have to use SwingUtilities.invokeLater() to run it on the EDT after all.
Michael Borgwardt