не работает компановщик (setLayout)

172
19 января 2019, 12:20

Застрял на одном месте, скорее всего не вижу очевидного.

есть приложение, по нажатию кнопок должны меняться панели (работает частично). Я хочу кнопки выставить на ЮГ, а они этого не хотят (располагаются наверху), и я не пойму как их заставить сделать это, посмотрите пожалуйста код, он очень простой, скажите в чем причина.

По факту у меня почему-то получается так, что сразу выходят две кнопки sweet и my button, sweet отображается правильно, как я и хочу, а my button где-то наверху, и если нажимать на sweet то ничего не происходит (а должна меняться панель), а если нажимать на my button, то sweet так же уползает наверх, и при этом панели меняются как надо.

enum ViewState {
    START_STATE, NEXT_STATE;
}
@SuppressWarnings("serial")
class Panel2 extends JPanel {
    public Panel2() {
        JPanel panel2 = new JPanel();
        panel2.setPreferredSize(new Dimension(1,40));
        add(panel2, BorderLayout.SOUTH);
        panel2.setLayout(new GridLayout());
        JButton button = new JButton("sweet");
        button.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                MyWindowTest.changeState(ViewState.START_STATE);
            }
        });
        panel2.add(button);
        this.add(panel2);
    }
}
@SuppressWarnings("serial")
class Panel1 extends JPanel {
    public Panel1() {
        JPanel panel1 = new JPanel();
        panel1.setPreferredSize(new Dimension(1,40));
        add(panel1, BorderLayout.SOUTH);
        panel1.setLayout(new GridLayout());
        JButton button = new JButton("my button");
        button.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                MyWindowTest.changeState(ViewState.NEXT_STATE);
            }
        });
        panel1.add(button);
        this.add(panel1);
    }
}
class MyWindowTest {
    private static ViewState viewState;
    private static JPanel mpanel;
    private static JPanel panel1;
    private static JPanel panel2;
    private static JFrame frame;
    public MyWindowTest() {
        frame = new JFrame();
        mpanel = new JPanel();
        panel1 = new Panel1();
        panel2 = new Panel2();
        frame.setSize(400, 400);
        frame.setLocationRelativeTo(null);
        frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
        frame.add(mpanel);
        frame.add(panel1, BorderLayout.SOUTH);
        panel1.setLayout(new GridLayout());
        frame.add(panel2, BorderLayout.SOUTH);
        panel2.setLayout(new GridLayout());

        changeState(ViewState.START_STATE);
        frame.setVisible(true);
    }
    public static void changeState(ViewState state) {
        viewState = state;
        System.out.println("change state: " + viewState);
        switch (state) {
            case START_STATE:
                mpanel.removeAll();
                mpanel.add(panel1);
                mpanel.revalidate();
                mpanel.repaint();
                break;
            case NEXT_STATE:
                mpanel.removeAll();
                mpanel.add(panel2);
                mpanel.revalidate();
                mpanel.repaint();
                break;
            default:
                System.out.println("UNKNOWN STATE!");
                break;
        }
    }
    public static void main(String[] args) {
        @SuppressWarnings("unused")
        MyWindowTest n = new MyWindowTest();
    }
}

Если есть предложения по улучшению кода, с радостью выслушаю.

Answer 1

GridLayout всегда сортирует компоненты только в порядке из добавления в контейнер. Вы не можете добавить компоненты в специфичное место, если вам надо поменять их положение, тогда надо добавить пустые компоненты. Например:

form.add(new JPanel());
form.add(new JPanel());
form.add(new JPanel());
form.add(new JPanel());

Возможно вы можете использовать GridBagLayout, который может это сделать, но его чуть сложнее использовать.

GridBagLayout поддерживает preferred size компонентов и использование GridBagLayout с GridBagConstraint свойствами:

  1. gridx, gridy
  2. anchor
  3. weightx, weighty
  4. gridwidth
  5. fill

    import java.awt.*;
    import java.awt.Dimension;
    import java.awt.GridBagConstraints;
    import java.awt.HeadlessException;
    import java.awt.Insets;
    import javax.swing.*;
    import javax.swing.SwingUtilities;
    /**
     *
     * @author Rashed
     */
    class GridBagLayoutDemo extends JFrame{
    
        public JLabel createLabel(String txt, int width, int height, Color color)
        {
            JLabel label = new JLabel(txt);
            label.setOpaque(true);
            label.setBackground(color);
            label.setPreferredSize(new Dimension(width, height));
            return label;
        }
        public GridBagLayoutDemo() throws HeadlessException {
            setSize(400,400);
            setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            JPanel panel = new JPanel(new java.awt.GridBagLayout());
            GridBagConstraints labCnst = new GridBagConstraints();
            labCnst.fill = GridBagConstraints.NONE;
            labCnst.insets = new Insets(3, 3, 3, 3);
            labCnst.anchor = GridBagConstraints.FIRST_LINE_START;
            labCnst.gridx  = 0;
            labCnst.gridy = 0;
            panel.add(createLabel("play", 100, 30, new Color(0x359DBD)), labCnst);
            // labCnst.anchor = GridBagConstraints.LAST_LINE_START;
            labCnst.gridx  = 0;
            labCnst.gridy = 2;
            panel.add(createLabel("Status: Ready!", 100, 30, new Color(0x359DBD)), labCnst);
            labCnst.anchor = GridBagConstraints.FIRST_LINE_END;
            labCnst.gridx  = 2;
            labCnst.gridy = 0;
            panel.add(createLabel("-0x", 100, 30, new Color(0x359DBD)), labCnst);
            labCnst.anchor = GridBagConstraints.LAST_LINE_END;
            labCnst.gridx  = 2;
            labCnst.gridy = 2;
            panel.add(createLabel("score:30", 100, 30, new Color(0x359DBD)), labCnst);
    
            labCnst.anchor = GridBagConstraints.LINE_START;
            labCnst.fill = GridBagConstraints.VERTICAL;
            labCnst.gridx  = 2;
            labCnst.gridy = 1;
            labCnst.gridwidth = 1;
            labCnst.weightx = 0.7;
            labCnst.weighty = 0.7;
            panel.add(createLabel("ScoreList", 100, 200, new Color(0xFFAA00)), labCnst);
    
            labCnst.gridx = 0;
            labCnst.gridy = 1;
            //labCnst.anchor = GridBagConstraints.LIN;
            labCnst.gridwidth = 2;
            labCnst.weightx = 0.8;
            labCnst.weighty = 0.8;
            labCnst.fill = GridBagConstraints.BOTH;
            panel.add(createLabel("It is the center", 200, 200, new Color(0xFFD47E)), labCnst);
            //labCnst.anchor = GridBagConstraints.LINE_END;
    
            add(panel);
        }
    
        public static void main(String[] args) {
            SwingUtilities.invokeLater(new Runnable() {
                @Override
                public void run() {
                    new GridBagLayoutDemo().setVisible(true);
                }
            });
        }
    }
    

Полностью описание приводить не буду, но можно найти тут: https://stackoverflow.com/questions/19707506/how-to-properly-use-gridlayout-to-position-elements-in-a-jframe

READ ALSO
Как подружить Payara (GlassFish) с MySQL

Как подружить Payara (GlassFish) с MySQL

Всем приветПытаюсь сделать свой небольшой pet-проект на Spring Boot с Payara в качестве Web сервера

165
Android. Внутренняя память. Данные появляются снова после переустановки

Android. Внутренняя память. Данные появляются снова после переустановки

У меня есть небольшая структура (из 6 текстовых полей примерно + дата), есть база которая содержит эти структурыБаза сохраняется и загружается...

109
Подсветка цифр в массиве

Подсветка цифр в массиве

У меня имеется массив чисел от 0 до 100 с повторениямиДлина массива N>100, например

126
Как передать данные между классами в Java [закрыт]

Как передать данные между классами в Java [закрыт]

Пробую писать программу на Java и столкнулся со следующей проблемой: у меня есть массив данных, который я генерирую в классе1, его нужно передать...

146