lep
lep

Reputation: 3

Vertical Scroll Bar for Radio Buttons

I'm a very new java programmer.

I'm trying to create a vertical list of radio buttons with a scroll bar. My code doesn't produce the window at the designated size, nor does the scroll bar actually appear.

import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.Toolkit;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

import javax.swing.Box;
import javax.swing.ButtonGroup;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JRadioButton;
import javax.swing.JScrollPane;

public class RadioButtonScroller {
    private List<String> abcList = new ArrayList<>(Arrays.asList("Aa", "Bb", "Cc", "Dd", "Ee", "Ff", "Gg", "Hh", "Ii",
            "Jj", "Kk", "Ll", "Mm", "Nn", "Oo", "Pp", "Qq", "Rr", "Ss", "Tt", "Uu", "Vv", "Ww", "Xx", "Yy", "Zz"));
    private JRadioButton pickButton;
    private JFrame jframe = new JFrame("Select one:");
    private JScrollPane scrollPane;
    private JPanel panel = new JPanel();
    private Box vertBox;

    public RadioButtonScroller() {
        createUI();
    }

    public void setRadioButtons() {
        ButtonGroup group = new ButtonGroup();

        for (int i = 0; i < abcList.size(); i++) {
            String theseLetters = abcList.get(i);
            pickButton = new JRadioButton(theseLetters);

            group.add(pickButton);
            vertBox.add(pickButton);
        }
    }

    private void createUI() {
        //centers on screen
        Dimension dim = Toolkit.getDefaultToolkit().getScreenSize();
        jframe.setLocationRelativeTo(null);
        jframe.setLocation(dim.width / 3 - jframe.getSize().width / 3, dim.height / 4 - jframe.getSize().height / 4);

        vertBox = Box.createVerticalBox();
        jframe.setSize(300, 525);
        vertBox.setSize(300, 525);
        jframe.setVisible(true);

        panel.setLayout(new FlowLayout());
        jframe.add(panel);
        scrollPane = new JScrollPane(vertBox);
        scrollPane.setSize(300, 525);
        scrollPane.getVerticalScrollBar();
        panel.add(scrollPane);

        jframe.pack();
        jframe.setVisible(true);
        jframe.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setRadioButtons();
    }

    public static void main(String[] args) {
        RadioButtonScroller radioButtonScroller = new RadioButtonScroller();
    }
}

I've successfully used JFrame with Vbox before, but the addition of JPanel & JScrollPane is getting me all mixed up.

(I cannot use JavaFX, due to some compatibility issues. Must be in swing.)

Many thanks.

Upvotes: 0

Views: 636

Answers (3)

lep
lep

Reputation: 3

Both responses led me to my answer, thank you both! Many thanks to George Z. and HoverCraft Full of Eels for pointing out that:

panel.setLayout(new FlowLayout()); 

would NOT work. It was George Z's clear suggestion to use:

panel.setLayout (new GridLayout(0, 1)); 

that worked for me.

While George Z. made it clear that:

scrollPane.setSize(300, 525);
scrollPane.getVerticalScrollBar();

were not accomplishing anything, it was Hovercraft Full Of Eels' mention of preferred size that helped me get all the way to the answer (and figure out where I went wrong in what I was trying to accomplish with those 2 wasted lines of code).

Hovercraft Full of Eels also helped me see what "packing" a JFrame actually does. You both gave what's needed, thank you so much. Here's a short, working answer:

import java.awt.Dimension;
import java.awt.GridLayout;
import java.awt.Toolkit;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

import javax.swing.Box;
import javax.swing.ButtonGroup;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JRadioButton;
import javax.swing.JScrollPane;

public class RadioButtonScroller {
    private List<String> abcList = new ArrayList<>(Arrays.asList("Aa", "Bb", "Cc", "Dd", "Ee", "Ff", "Gg", "Hh", "Ii",
            "Jj", "Kk", "Ll", "Mm", "Nn", "Oo", "Pp", "Qq", "Rr", "Ss", "Tt", "Uu", "Vv", "Ww", "Xx", "Yy", "Zz"));
    private JRadioButton pickButton;
    private JFrame jframe = new JFrame("Select one:");
    private JScrollPane scrollPane;
    private JPanel panel = new JPanel();
    private Box vertBox;

    public RadioButtonScroller() {
        createUI();
    }

    public void setRadioButtons() {
        ButtonGroup group = new ButtonGroup();

        for (int i = 0; i < abcList.size(); i++) {
            String theseLetters = abcList.get(i);
            pickButton = new JRadioButton(theseLetters);

            group.add(pickButton);
            vertBox.add(pickButton);
        }
        jframe.pack();
        jframe.setVisible(true);
        jframe.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    }

    private void createUI() {
        // center on screen
        Dimension dim = Toolkit.getDefaultToolkit().getScreenSize();
        jframe.setLocationRelativeTo(null);
        jframe.setLocation(dim.width / 3 - jframe.getSize().width / 3, dim.height / 4 - jframe.getSize().height / 4);

        vertBox = Box.createVerticalBox();
        jframe.setSize(300, 525);
        vertBox.setSize(300, 525);
        jframe.setVisible(true);

        panel.setLayout(new GridLayout(0, 1));
        jframe.add(panel);
        scrollPane = new JScrollPane(vertBox);
        scrollPane.setPreferredSize(new Dimension(300, 525));
        panel.add(scrollPane);

        setRadioButtons();
    }

    public static void main(String[] args) {
        RadioButtonScroller radioButtonScroller = new RadioButtonScroller();
    }
}

Upvotes: 0

Hovercraft Full Of Eels
Hovercraft Full Of Eels

Reputation: 285403

Lot's of layout issues here

  1. layout managers, for the most part, do not respect a component's size, but rather its preferred size.
  2. And JScrollPane's size is controlled by its viewport's preferred size.
  3. FlowLayout is very basic and unforgiving and will often not work well with complex combination layouts.
  4. Don't add components after packing your JFrame but rather before. Else the components and layout managers won't size themselves accordingly.

e.g.,

import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.GridLayout;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import javax.swing.*;

@SuppressWarnings("serial")
public class RadioButtonScroller2 extends JPanel {
    private List<String> abcList = new ArrayList<>(Arrays.asList("Aa", "Bb", "Cc", "Dd", "Ee", "Ff", "Gg", "Hh", "Ii",
            "Jj", "Kk", "Ll", "Mm", "Nn", "Oo", "Pp", "Qq", "Rr", "Ss", "Tt", "Uu", "Vv", "Ww", "Xx", "Yy", "Zz"));
    private ButtonGroup buttonGroup = new ButtonGroup();

    public RadioButtonScroller2() {
        JPanel radioPanel = new JPanel(new GridLayout(0, 1));
        ItemListener il = itemEvent -> {
            if (itemEvent.getStateChange() == ItemEvent.SELECTED) {
                AbstractButton btn = (AbstractButton) itemEvent.getSource();
                System.out.println("Selection: " + btn.getActionCommand());
            }
        };
        for (String radioText : abcList) {
            JRadioButton radioButton = new JRadioButton(radioText);
            radioButton.setActionCommand(radioText);
            radioButton.addItemListener(il);
            radioPanel.add(radioButton);
            buttonGroup.add(radioButton);
        }

        JScrollPane scrollPane = new JScrollPane(radioPanel);
        scrollPane.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);
        scrollPane.getViewport().setPreferredSize(new Dimension(150, 200));

        setLayout(new BorderLayout());
        add(scrollPane);
    }

    private static void createAndShowGui() {
        RadioButtonScroller2 mainPanel = new RadioButtonScroller2();

        JFrame frame = new JFrame("Test");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.getContentPane().add(mainPanel);
        frame.pack();
        frame.setLocationRelativeTo(null);
        frame.setVisible(true);
    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(() -> createAndShowGui());
    }
}

Upvotes: 2

George Z.
George Z.

Reputation: 6808

Its the layout you are using in panel.setLayout(new FlowLayout());. Flow layout "does not work well" with JScrollPane. You can change the layout and you will get a functional scroll pane without having to do extra stuff. (In order to make flow layout work with a JScrollPane, you will have to investigate further, probably with componentlisteners etc)

In your case I would use a GridLayout with 1 column, infinite rows:

panel.setLayout(new GridLayout(0, 1));

Or a BoxLayout with y axis:

panel.setLayout(new BoxLayout(panel, BoxLayout.Y_AXIS));

Also, these lines play no role:

scrollPane.setSize(300, 525);
scrollPane.getVerticalScrollBar();

Scrollpane's size will be calculated from parent container, which is JFrame's content pane.

Upvotes: 1

Related Questions