Можно ли динамически добавлять компоненты в группы в GroupLayout?

Можно Componentбыть добавлены в группы в GroupLayout динамически, после setHorizontalGroup() а такжеsetVerticalGroup() были вызваны без сброса макета? Я работаю над графическим интерфейсом для проекта, который поможет студентам найти лучший способ составить расписание занятий на неделю. Это включает ввод информации о времени занятий и т. Д. Для неизвестного количества классов. Конечно, я не могу просто добавить сколь угодно большое количество форм, чтобы пользователь мог поместить информацию и сказать: "Никто не может рассматривать больше, чем это количество классов", поэтому пользователь должен иметь возможность добавлять новые формы в их собственный. Я могу создавать формы, но не могу найти способ успешно добавить их в GroupLayout в окне без повторного вызова setHorizontalGroup(...) или же setVerticalGroup(...), которые пишут поверх предыдущего Groupс, а не добавить к ним. Это релевантная часть кода, который у меня есть (прокомментирован для разборчивости):

 private static void createAndShowGUI() {
    //Create window and assign an empty GroupLayout to it
    JFrame frame = new JFrame();
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    GroupLayout layout = new GroupLayout(frame.getContentPane());
    frame.getContentPane().setLayout(layout);

    /*WeekPanel extends JPanel, and is the "form" the user enters data into. 
    In essence, it's a JPanel with a series of JTextFields.*/
    WeekPanel panel1 = new WeekPanel();
    WeekPanel panel2 = new WeekPanel();

    //The layout code below places two WeekPanels in the window, one on top of the other
    layout.setHorizontalGroup(layout.createSequentialGroup()
            .addGroup(layout.createParallelGroup()
                    .addComponent(panel1)
                    .addComponent(panel2)));
    layout.setVerticalGroup(layout.createSequentialGroup()
            .addComponent(panel1)
            .addComponent(panel2));

    /*I would like to add a component to the layout here as proof of concept.*/
    frame.pack();
    frame.setVisible(true);
}

Я пробовал звонить frame.add([some component]) как раз перед frame.pack(), но это никогда не имеет никакого видимого значения. Я посмотрел на официальную документацию для GroupLayout, и я не вижу способа получить доступ или изменить горизонтальный / вертикальный Groupв GroupLayoutили даже поле, относящееся к тем Groupс, в этом отношении. Я в полной растерянности относительно того, что делать здесь. Я хочу избежать изучения нового типа Layout если это вообще возможно, но я начинаю бояться, что мне придется (или, что еще хуже, то, что я пытаюсь сделать, с самого начала невозможно).

1 ответ

Как показано здесь, вы можете использовать этот подход:

  1. Сначала создайте необходимый ParallelGroup а также SequentialGroup,
  2. Позже добавьте нужные группы и компоненты, представляющие новую строку.

В приведенном ниже примере add() добавляет новую метку и текстовое поле к макету. AdjustmentListener, предлагается здесь, прокрутка до последней добавленной строки.

образ

import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.event.ActionEvent;
import java.awt.event.AdjustmentEvent;
import javax.swing.AbstractAction;
import javax.swing.GroupLayout;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextField;

/**
 * @see https://stackru.com/a/41926375/230513
 * @see https://stackru.com/a/14858272/230513
 * @see https://stackru.com/a/8504753/230513
 * @see https://stackru.com/a/14011536/230513
 */
public class DynamicGroupLayout {

    private static final int NUM = 6;
    private GroupLayout layout;
    private GroupLayout.ParallelGroup parallel;
    private GroupLayout.SequentialGroup sequential;
    private int i;

    private JPanel create() {
        JPanel panel = new JPanel();
        layout = new GroupLayout(panel);
        panel.setLayout(layout);
        layout.setAutoCreateGaps(true);
        layout.setAutoCreateContainerGaps(true);
        parallel = layout.createParallelGroup();
        layout.setHorizontalGroup(layout.createSequentialGroup().addGroup(parallel));
        sequential = layout.createSequentialGroup();
        layout.setVerticalGroup(sequential);
        for (int i = 0; i < NUM; i++) {
            add();
        }
        return panel;
    }

    private void add() {
        JLabel label = new JLabel(String.valueOf(i + 1), JLabel.RIGHT);
        JTextField field = new JTextField(String.valueOf("String " + (i + 1)));
        label.setLabelFor(field);
        parallel.addGroup(layout.createSequentialGroup().
            addComponent(label).addComponent(field));
        sequential.addGroup(layout.createParallelGroup(GroupLayout.Alignment.BASELINE).
            addComponent(label).addComponent(field));
        i++;
    }

    public static void main(String[] args) {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                JFrame f = new JFrame("DynamicGroupLayout");
                f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                final DynamicGroupLayout dgl = new DynamicGroupLayout();
                final JPanel panel = dgl.create();
                JScrollPane jsp = new JScrollPane(panel) {
                    @Override
                    public Dimension getPreferredSize() {
                        return new Dimension(320, 240);
                    }
                };
                jsp.getVerticalScrollBar().addAdjustmentListener((AdjustmentEvent e) -> {
                    e.getAdjustable().setValue(e.getAdjustable().getMaximum());
                });
                f.add(jsp);
                JPanel controls = new JPanel();
                controls.add(new JButton(new AbstractAction("Add") {
                    @Override
                    public void actionPerformed(ActionEvent e) {
                        dgl.add();
                        panel.validate();
                    }
                }));
                f.add(controls, BorderLayout.SOUTH);
                f.pack();
                f.setLocationRelativeTo(null);
                f.setVisible(true);
            }
        });
    }
}
Другие вопросы по тегам