Вертикальная полоса прокрутки для переключателей

Я очень новый программист Java.

Я пытаюсь создать вертикальный список переключателей с полосой прокрутки. Мой код не создает окно заданного размера, и на самом деле не появляется полоса прокрутки.

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();
    }
}

Раньше я успешно использовал JFrame с Vbox, но добавление JPanel и JScrollPane запутало меня.

(Я не могу использовать JavaFX из-за некоторых проблем с совместимостью. Должен быть в разработке.)

Большое спасибо.


person lep    schedule 09.12.2019    source источник


Ответы (3)


Это макет, который вы используете в panel.setLayout(new FlowLayout());. Схема потока «плохо работает» с JScrollPane. Вы можете изменить макет, и вы получите функциональную панель прокрутки без необходимости делать дополнительные действия. (Чтобы заставить макет потока работать с JScrollPane, вам придется продолжить расследование, возможно, с компонентными слушателями и т. д.)

В вашем случае я бы использовал GridLayout с 1 столбцом, бесконечными строками:

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

Или BoxLayout с осью Y:

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

Кроме того, эти строки не играют никакой роли:

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

Размер панели прокрутки будет рассчитан из родительского контейнера, который является панелью содержимого JFrame.

person George Z.    schedule 09.12.2019

Здесь много проблем с макетом

  1. менеджеры компоновки, по большей части, не учитывают размер компонента, а скорее его предпочтительный размер.
  2. И размер JScrollPane контролируется предпочтительным размером области просмотра.
  3. FlowLayout очень прост и неумолим и часто плохо работает со сложными комбинированными макетами.
  4. Добавляйте компоненты не после упаковки вашего JFrame, а до. В противном случае компоненты и менеджеры компоновки не будут иметь соответствующих размеров.

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());
    }
}
person Hovercraft Full Of Eels    schedule 09.12.2019
comment
Что такое видовой экран? - person lep; 10.12.2019
comment
@lep: каждый JScrollPane имеет область просмотра в качестве первого и основного компонента. Компонент, который отображается в JScrollPane, удерживается в окне просмотра как его представление. Это хорошо объяснено с картинками в JScrollPane. Учебник. Посмотрите эту ссылку. - person Hovercraft Full Of Eels; 10.12.2019

Оба ответа привели меня к моему ответу, спасибо вам обоим! Большое спасибо Джорджу З. и HoverCraft Full of Eels за указание на то, что:

panel.setLayout(new FlowLayout()); 

НЕ будет работать. Это было четкое предложение Джорджа З. использовать:

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

это сработало для меня.

В то время как Джордж З. дал понять, что:

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

ничего не добились, именно упоминание предпочтительного размера от Hovercraft Full Of Eels помогло мне добраться до ответа (и выяснить, где я ошибся в том, что я пытался достичь с этими 2 потерянные строки кода).

Hovercraft Full of Eels также помог мне увидеть, что на самом деле делает «упаковка» JFrame. Вы оба дали то, что нужно, большое спасибо. Вот краткий рабочий ответ:

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();
    }
}
person lep    schedule 09.12.2019