Вертикальное выравнивание нижней панели

Я хочу вертикально выровнять 3 кнопки на нижней панели.

Вот что я написал:

ClientWindow(){
    pickBtn = new JButton();
    attackBtn = new JButton();
    placeBtn = new JButton();
    
    JPanel userPanel = new JPanel();
    userPanel.setPreferredSize(new Dimension(100,100));
    userPanel.setBackground(Color.red);
    
    JFrame frame = new JFrame();
    frame.setTitle("Test");
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    frame.setLayout(new BorderLayout());
    frame.setResizable(false);
    frame.setSize(1280,720);
    frame.setLocationRelativeTo(null);
    
    frame.add(userPanel,BorderLayout.SOUTH);
    
    userPanel.add(pickBtn);
    userPanel.add(attackBtn);
    userPanel.add(placeBtn);
    
    frame.setVisible(true);
}

Как я могу выровнять их по вертикали?

DYM 3 кнопки в ряд или 3 кнопки в столбец?

Andrew Thompson 07.04.2022 22:53

3 кнопки подряд

Diaskyyy 07.04.2022 22:53

FlowLayout (макет JPanel по умолчанию) должен делать это автоматически. КСТАТИ: Не звоните [Container].setPreferredSize(..) или [Window].setSize(..). Какие бы числа ни были предоставлены, они будут: а) догадкой и б) неправильным.

Andrew Thompson 07.04.2022 22:56

Хм, я очень новичок в свинге. что вы предлагаете мне использовать?

Diaskyyy 07.04.2022 22:59

Для КСТАТИ? Window.pack() после добавления всех компонентов.

Andrew Thompson 07.04.2022 23:01

да, но для размера компонентов? Удалив все, теперь окно очень маленькое

Diaskyyy 07.04.2022 23:03

Есть несколько способов увеличить размер кнопок. НАПРИМЕР. Установите более длинный текст или более крупный значок, шрифт или Insets. Для панели добавьте EmptyBorder. Кроме того, в большинстве макетов есть способы увеличить расстояние между компонентами. Для получения дополнительной информации см. документацию по конструкторам.

Andrew Thompson 07.04.2022 23:06

да, но как я могу выровнять эти кнопки по вертикали?

Diaskyyy 07.04.2022 23:22

Мне непонятно, что вы имеете в виду. Предоставьте графическое изображение ASCII или простой рисунок графического интерфейса с размером по умолчанию и при перетаскивании большего размера по ширине и высоте.

Andrew Thompson 07.04.2022 23:32
prnt.sc/IezXEDqLPCeh
Diaskyyy 08.04.2022 17:17
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
0
10
35
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Взгляните на Размещение компонентов внутри контейнера

Например, в следующем примере используется GridBagLayout

import java.awt.BorderLayout;
import java.awt.EventQueue;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.border.EmptyBorder;

public class Main {
    public static void main(String[] args) {
        new Main();
    }

    public Main() {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                JLabel label = new JLabel("This is just here to make some content");
                label.setBorder(new EmptyBorder(32, 32, 32, 32));

                JFrame frame = new JFrame();
                frame.add(label);
                frame.add(new UserPanel(), BorderLayout.SOUTH);
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
            }
        });
    }

    public class UserPanel extends JPanel {

        public UserPanel() {
            JButton pickBtn = new JButton("Pick");
            JButton attackBtn = new JButton("Attack");
            JButton placeBtn = new JButton("Place");

            setLayout(new GridBagLayout());
            GridBagConstraints gbc = new GridBagConstraints();
            gbc.gridwidth = GridBagConstraints.REMAINDER;
            gbc.fill = GridBagConstraints.HORIZONTAL;

            add(pickBtn, gbc);
            add(attackBtn, gbc);
            add(placeBtn, gbc);
        }
    }
}

Сделать ButtonLayout

Важный

Обратите внимание: следующее предназначено для замены GridBagLayout из приведенного выше примера, поскольку GridBagLayout сложно и может быть немного излишним для этой цели.


ДЕЙСТВИТЕЛЬНО давно я натолкнулся на действительно изящную концепцию ButtonLayout, которая в основном предоставляла простой менеджер компоновки для кнопок компоновки, аналогичный тому, как это делает большинство ОС (т.е. кнопки имеют одинаковый размер).

Ниже приведен ОЧЕНЬ простой пример этой концепции.

import java.awt.Color;
import java.awt.Component;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.LayoutManager2;
import java.awt.Point;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.border.LineBorder;

public class Main {
    public static void main(String[] args) {
        new Main();
    }

    public Main() {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                JFrame frame = new JFrame();
                frame.add(new UserPanel());
                frame.setSize(400, 400);
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
            }
        });
    }

    public class UserPanel extends JPanel {

        public UserPanel() {
            JButton pickBtn = new JButton("Pick");
            JButton attackBtn = new JButton("Attack");
            JButton placeBtn = new JButton("Place");

            setBorder(new LineBorder(Color.BLACK));
            setLayout(new ButtonLayout(ButtonLayout.Alignment.VERTICAL, ButtonLayout.Anchor.TRAILING));
            add(pickBtn);
            add(attackBtn);
            add(placeBtn);
        }
    }

    public class ButtonLayout implements LayoutManager2 {

        public enum Alignment {
            VERTICAL, HORIZONTAL
        }

        public enum Anchor {
            LEADING, CENTER, TRAILING
        }

        private Alignment alignment;
        private Anchor anchor;
        private int padding;

        private Dimension virtualBounds;

        public ButtonLayout() {
            this(Alignment.HORIZONTAL, Anchor.TRAILING, 0);
        }

        public ButtonLayout(Alignment alignment, Anchor anchor) {
            this(alignment, anchor, 0);
        }

        public ButtonLayout(Alignment alignment, Anchor anchor, int padding) {
            this.alignment = alignment;
            this.padding = padding;
            this.anchor = anchor;
        }

        public Alignment getAlignment() {
            return alignment;
        }

        public Anchor getAnchor() {
            return anchor;
        }

        protected int getPadding() {
            return padding;
        }

        protected int getTotalPadding(Container parent) {
            int padding = getPadding();
            return (padding * parent.getComponentCount()) - padding;
        }

        @Override
        public void addLayoutComponent(Component comp, Object constraints) {
        }

        @Override
        public void addLayoutComponent(String name, Component comp) {
        }

        @Override
        public void removeLayoutComponent(Component comp) {
        }

        @Override
        public void invalidateLayout(Container target) {
            virtualBounds = null;
        }

        protected Dimension virtualLayout(Container parent) {
            if (virtualBounds != null) {
                return virtualBounds;
            }
            int maxWidth = 0;
            int maxHeight = 0;

            for (Component component : parent.getComponents()) {
                Dimension preferredSize = component.getPreferredSize();
                maxHeight = Math.max(maxHeight, preferredSize.height);
                maxWidth = Math.max(maxWidth, preferredSize.width);
            }

            int padding = 0;
            int width = 0;
            int height = 0;
            int componentCount = parent.getComponentCount();
            switch (alignment) {
                case HORIZONTAL:
                    width = (maxWidth * componentCount) + getTotalPadding(parent);
                    height = maxHeight;
                    break;
                case VERTICAL:
                    width = maxWidth;
                    height = (maxHeight * componentCount) + getTotalPadding(parent);
                    break;
            }

            virtualBounds = new Dimension(width, height);
            return virtualBounds;
        }

        @Override
        public Dimension maximumLayoutSize(Container parent) {
            return virtualLayout(parent);
        }

        @Override
        public Dimension preferredLayoutSize(Container parent) {
            return virtualLayout(parent);
        }

        @Override
        public Dimension minimumLayoutSize(Container parent) {
            return virtualLayout(parent);
        }

        @Override
        public float getLayoutAlignmentX(Container target) {
            return 0.5f;
        }

        @Override
        public float getLayoutAlignmentY(Container target) {
            return 0.5f;
        }

        @Override
        public void layoutContainer(Container parent) {
            int maxWidth = 0;
            int maxHeight = 0;

            for (Component component : parent.getComponents()) {
                Dimension preferredSize = component.getPreferredSize();
                maxHeight = Math.max(maxHeight, preferredSize.height);
                maxWidth = Math.max(maxWidth, preferredSize.width);
            }

            Dimension defaultSize = new Dimension(maxWidth, maxHeight);
            Point point = offsetForAnchor(parent, defaultSize);

            int xDelta = 0;
            int yDelta = 0;
            switch (alignment) {
                case HORIZONTAL:
                    xDelta = getPadding() + defaultSize.width;
                    break;
                case VERTICAL:
                    yDelta = getPadding() + defaultSize.height;
                    break;
            }
            for (Component component : parent.getComponents()) {
                component.setSize(defaultSize);
                component.setLocation(point);
                point = new Point(point.x + xDelta, point.y + yDelta);
            }
        }

        protected Point offsetForAnchor(Container parent, Dimension defaultSize) {
            switch (anchor) {
                case LEADING:
                    return leadingOffSet(parent, defaultSize);
                case TRAILING:
                    return trailingOffSet(parent, defaultSize);
                case CENTER:
                    return centerOffSet(parent, defaultSize);
            }
            return new Point(0, 0);
        }

        protected Point leadingOffSet(Container parent, Dimension defaultSize) {
            Point point = new Point(0, 0);
            switch (alignment) {
                case HORIZONTAL:
                    point.x = padding;
                    point.y = (parent.getHeight() - defaultSize.height) / 2;
                    break;
                case VERTICAL:
                    point.x = (parent.getWidth() - defaultSize.width) / 2;
                    point.y = padding;
                    break;
            }
            return point;
        }

        protected Point trailingOffSet(Container parent, Dimension defaultSize) {
            Point point = new Point(0, 0);
            int componentCount = parent.getComponentCount();
            switch (alignment) {
                case HORIZONTAL:
                    int totalWidth = (defaultSize.width * componentCount) + getTotalPadding(parent);
                    point.x = parent.getWidth() - totalWidth;
                    point.y = (parent.getHeight() - defaultSize.height) / 2;
                    break;
                case VERTICAL:
                    int totalHeight = (defaultSize.height * componentCount) + getTotalPadding(parent);
                    point.x = (parent.getWidth() - defaultSize.width) / 2;
                    point.y = parent.getHeight() - totalHeight;
                    break;
            }
            return point;
        }

        protected Point centerOffSet(Container parent, Dimension defaultSize) {
            Point point = new Point(0, 0);
            int componentCount = parent.getComponentCount();
            switch (alignment) {
                case HORIZONTAL: {
                    int totalWidth = (defaultSize.width * componentCount) + getTotalPadding(parent);
                    point.x = (parent.getWidth() - totalWidth) / 2;
                    point.y = (parent.getHeight() - defaultSize.height) / 2;
                }
                break;
                case VERTICAL: {
                    int totalHeight = (defaultSize.height * componentCount) + getTotalPadding(parent);
                    point.x = (parent.getWidth() - defaultSize.width) / 2;
                    point.y = (parent.getHeight() - totalHeight) / 2;
                }
                break;
            }
            return point;
        }

    }
}

как разместить кнопки друг рядом с другом? (по горизонтали)

Diaskyyy 08.04.2022 00:07

@Diaskyyy Вы должны прочитать связанный учебник. Вы «могли бы» просто использовать FlowLayout, как раньше, или вы могли бы использовать GridBagConstraints#gridy (вместо (GridBagConstraints#gridwidth), но вы потеряете «равный размер»

MadProgrammer 08.04.2022 00:11

это очень мило, но это не совсем то, что я искал. Я искал панель в нижней части окна. затем я хочу, чтобы кнопки были выровнены по горизонтали друг относительно друга, но по вертикали относительно панели. prnt.sc/IezXEDqLPCeh небольшая ничья.

Diaskyyy 08.04.2022 17:13

когда я использую ButtonLayout.Alignment.HORIZONTAL и ButtonLayout.Anchor.CENTER, они находятся в середине окна. И когда я ButtonLayout.Alignment.VERTICAL и ButtonLayout.Anchor.CENTER, они снизу, но выровнены по вертикали

Diaskyyy 08.04.2022 17:15

@Diaskyyy Когда я использую HORIZONTAL/CENTER и VERTICAL/CENTER, компоненты привязываются к середине компонента — цель макета Button состоит в том, чтобы воздействовать ТОЛЬКО на кнопки. Итак, судя по тому, что вы рисуете, панель «кнопка» должна быть с использованием HORIZONTAL/CENTER, а сама панель размещена в позиции SOUTH в BorderLayout, как и в первом примере — это широко известно как составные макеты, где вы используете ряд компонентов. со своими собственными макетами для создания сложных представлений

MadProgrammer 08.04.2022 23:56

Другие вопросы по теме