LayoutManager для компонентов разного размера без кодирования абсолютных позиций

Я пытаюсь создать пользовательский интерфейс, но не знаю, как использовать для этого LayoutManger.

Как показано на изображении, компонент фиолетового цвета имеет фиксированную ширину и высоту, но придерживается углов. 8 и 4 имеют фиксированную и переменную высоту, 2 и 6 имеют фиксированную высоту и переменную ширину. средний компонент (9) требует переменной ширины и высоты.

Эти 8 компонентов работают как граница, а размер среднего необходимо изменить в соответствии с размером родительского компонента. Я мог бы сделать это, кодируя абсолютные позиции, используя нулевой макет. но я предложил не использовать нулевой макет.

Как я могу сделать это с макетом ведьмы менеджера макетов, который я могу использовать для этого? Нужно ли использовать больше макетов, чем один?

ОБНОВЛЯТЬ

я пробовал кое-что с GridBagLayout как предложение Эндрю, но мне все еще нужна небольшая помощь, чтобы понять, как это работает. Вот мой код

 import java.awt.Color;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;

public class GridLayoutTest {
    
    
    
    public static void main(String[] args) {
        JFrame frame = new JFrame();
        JPanel jPanel1 = new JPanel();
        jPanel1.setLayout(new GridBagLayout());
        
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        
        
        
        
        JButton button;

        GridBagConstraints c = new GridBagConstraints();

        button = new JButton("1");
        c.fill = GridBagConstraints.VERTICAL;
        c.anchor = GridBagConstraints.FIRST_LINE_START;
        c.gridx = 0;
        c.gridy = 0;
        jPanel1.add(button, c);

        button = new JButton("2");
        c.fill = GridBagConstraints.HORIZONTAL;
        c.weightx = 1.0;
        c.gridx = 1;
        c.gridy = 0;
        jPanel1.add(button, c);

        button = new JButton("3");
        c.fill = GridBagConstraints.VERTICAL;
        c.anchor = GridBagConstraints.FIRST_LINE_END;
        c.gridx = 2;
        c.gridy = 0;
        jPanel1.add(button, c);

        button = new JButton("4");
        c.fill = GridBagConstraints.VERTICAL;
        c.anchor = GridBagConstraints.LINE_START;
        c.weighty = 1.0;
        c.gridx = 0;
        c.gridy = 1;
        jPanel1.add(button, c);

        //Panel
        JPanel panel = new JPanel();
        panel.setBackground(Color.green.darker());
        c.fill = GridBagConstraints.BOTH;
        c.weightx = 0.0;
        //c.weightx = 1.0;
        c.gridx = 1;
        c.gridy = 1;
        jPanel1.add(panel, c);

        button = new JButton("5");
        c.fill = GridBagConstraints.VERTICAL;
        c.anchor = GridBagConstraints.LINE_END;
        c.weighty = 1.0;
        c.gridx = 2;
        c.gridy = 1;
        jPanel1.add(button, c);

        button = new JButton("6");
        c.fill = GridBagConstraints.VERTICAL;
        c.anchor = GridBagConstraints.LAST_LINE_START;
        c.gridx = 0;
        c.gridy = 2;
        jPanel1.add(button, c);

        button = new JButton("7");
        c.fill = GridBagConstraints.HORIZONTAL;
        c.weightx = 1.0;
        c.gridx = 1;
        c.gridy = 2;
        jPanel1.add(button, c);

        button = new JButton("8");
        c.fill = GridBagConstraints.VERTICAL;
        c.anchor = GridBagConstraints.LAST_LINE_END;
        c.gridx = 2;
        c.gridy = 2;
        jPanel1.add(button, c);
        
        
        frame.add(jPanel1);
        
        frame.pack();
        frame.setLocationRelativeTo(null);
        frame.setSize(500, 500);
        frame.setVisible(true);
        
    }
   
}

Этого можно добиться, используя GridBagLayout с соответствующими ограничениями. Попробуйте и верните нам минимально воспроизводимый пример, если вы застряли.

Andrew Thompson 14.12.2020 13:24

@ Эндрю Томпсон, я попробую. Спасибо

dins88 14.12.2020 13:35

Если вы хотите увидеть JPanel, который выглядит так, как вы предлагаете, я недавно создал Qlocktwo. Основная панель JPanel состоит из 9 подчиненных панелей JPanel.

Gilbert Le Blanc 14.12.2020 16:29

Нужно ли использовать больше макетов, чем один? - это всегда вариант при разработке макета формы. Однако я согласен, что с этим требованием GridBagLayout должен решить проблему.

camickr 14.12.2020 16:47

@AndrewThompson нужна небольшая помощь, если вы не возражаете.

dins88 15.12.2020 10:49

«нужна небольшая помощь, если вы не возражаете» Вы обратились к нужному человеку за помощью в минимально воспроизводимом примере. MRE должен включать импорт и метод main. Все, что ему нужно для чистой компиляции и запуска, чтобы показать проблему в нашей IDE.

Andrew Thompson 15.12.2020 10:55

@AndrewThompson Теперь я обновил код.

dins88 15.12.2020 11:12
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
2
7
55
3
Перейти к ответу Данный вопрос помечен как решенный

Ответы 3

Другим вариантом может быть JGoodies FormLayout . Я использую это в сочетании с JFormDesigner для всех своих потребностей в макетировании практически всегда. Он покрывает 95% процентов моих вариантов использования. Остальные 5% — это BorderLayout и абсолютное позиционирование (нулевой макет).

Обычная стратегия решения сложных вычислительных задач состоит в том, чтобы разбить их на небольшие, четко определенные управляемые задачи. Разделяй и властвуй. Это также относится к графическому интерфейсу: вы можете разбить дизайн на небольшие, удобные для компоновки контейнеры. В этом случае нужный макет может быть достигнут с помощью BoxLayout и BorderLayout:

import java.awt.*;
import javax.swing.Box.Filler;
import javax.swing.*;


public class FramedContent extends JPanel{

    private static final int FRAME_WIDTH = 35, CONTENT_SIZE = 300, BORDER_SIZE = 1;
    private static final Color CORNER_COLOR = Color.MAGENTA, RULLER_COLOR = Color.BLUE,
                                CONTENT_COLOR = Color.GREEN, BORDER_COLOR = Color.WHITE;
    FramedContent(){
        setLayout(new BorderLayout());
        add(header(), BorderLayout.NORTH);
        add(center(), BorderLayout.CENTER);
        add(header(), BorderLayout.SOUTH);
    }

    private JPanel header(){
        JPanel hExpandPane = new JPanel();
        hExpandPane.setLayout(new BoxLayout(hExpandPane, BoxLayout.X_AXIS));
        hExpandPane.add(corner());
        hExpandPane.add(hRuller());
        hExpandPane.add(corner());
        return hExpandPane;
    }

    private JComponent corner(){
        Dimension d = new Dimension(FRAME_WIDTH, FRAME_WIDTH);
        Filler filler = new Filler(d, d, d);
        filler.setBackground(CORNER_COLOR);
        filler.setBorder(BorderFactory.createLineBorder(BORDER_COLOR, BORDER_SIZE));
        filler.setOpaque(true);
        return filler;
    }

    private JComponent hRuller(){
        Dimension d = new Dimension(0,FRAME_WIDTH);
        Filler filler = new Filler(d, d, new Dimension(Short.MAX_VALUE, FRAME_WIDTH));
        filler.setBackground(RULLER_COLOR);;
        filler.setOpaque(true);
        return filler;
    }

    private JPanel center(){
        JPanel vExpandPane = new JPanel();
        vExpandPane.setLayout(new BorderLayout());
        vExpandPane.add(vRuller(), BorderLayout.WEST);
        vExpandPane.add(content(), BorderLayout.CENTER);
        vExpandPane.add(vRuller(), BorderLayout.EAST);
        return vExpandPane;
    }

    private JComponent vRuller(){
        Dimension d = new Dimension(FRAME_WIDTH, 0);
        Filler filler = new Filler(d, d, new Dimension(FRAME_WIDTH, Short.MAX_VALUE));
        filler.setBackground(RULLER_COLOR);
        filler.setOpaque(true);
        return filler;
    }

    private JPanel content(){
        JPanel content = new JPanel(new GridBagLayout());// GridBagLayout used just to center the content
        content.setBackground(CONTENT_COLOR);
        content.add(new JLabel("Your Content Goes Here"));
        content.setPreferredSize(new Dimension(CONTENT_SIZE,CONTENT_SIZE));
        return content;
    }

    public static void createWindow()   {
        JFrame frame = new JFrame("Framed content");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setLocationRelativeTo(null);
        frame.add(new FramedContent());
        frame.pack();
        frame.setVisible(true);
    }

    public static void main(String[] args) {
        createWindow();
    }
}

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

Я создал следующий графический интерфейс.

Я установил все шесть ограничений GridBagConstraints (якорь, заполнение, сеткаx, сетка, весx, вес) для каждого элемента сетки. Таким образом, мне было легче отслеживать значения каждого элемента.

Вот полный исполняемый код, который я использовал. Другими словами, минимальный воспроизводимый пример.

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;

public class GridBagLayoutGUI implements Runnable {

    public static void main(String[] args) {
        SwingUtilities.invokeLater(new GridBagLayoutGUI());
    }

    @Override
    public void run() {
        JFrame frame = new JFrame("GridBagLayout GUI");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        frame.add(createMainPanel(), BorderLayout.CENTER);

        frame.pack();
        frame.setLocationByPlatform(true);
        frame.setVisible(true);
    }

    private JPanel createMainPanel() {
        JPanel panel = new JPanel(new GridBagLayout());
        panel.setPreferredSize(new Dimension(300, 300));

        JButton button;

        GridBagConstraints c = new GridBagConstraints();

        button = new JButton("1");
        c.fill = GridBagConstraints.NONE;
        c.anchor = GridBagConstraints.FIRST_LINE_START;
        c.weightx = 0.0d;
        c.weighty = 0.0d;
        c.gridx = 0;
        c.gridy = 0;
        panel.add(button, c);

        button = new JButton("2");
        c.fill = GridBagConstraints.HORIZONTAL;
        c.anchor = GridBagConstraints.CENTER;
        c.weightx = 1.0d;
        c.weighty = 0.0d;
        c.gridx = 1;
        c.gridy = 0;
        panel.add(button, c);

        button = new JButton("3");
        c.fill = GridBagConstraints.NONE;
        c.anchor = GridBagConstraints.FIRST_LINE_END;
        c.weightx = 0.0d;
        c.weighty = 0.0d;
        c.gridx = 2;
        c.gridy = 0;
        panel.add(button, c);

        button = new JButton("4");
        c.fill = GridBagConstraints.VERTICAL;
        c.anchor = GridBagConstraints.LINE_START;
        c.weightx = 0.0d;
        c.weighty = 1.0d;
        c.gridx = 0;
        c.gridy = 1;
        panel.add(button, c);

        // Panel
        JPanel innerPanel = new JPanel();
        innerPanel.setBackground(Color.green.darker());
        c.fill = GridBagConstraints.BOTH;
        c.anchor = GridBagConstraints.CENTER;
        c.weightx = 1.0d;
        c.weighty = 1.0d;
        c.gridx = 1;
        c.gridy = 1;
        panel.add(innerPanel, c);

        button = new JButton("5");
        c.fill = GridBagConstraints.VERTICAL;
        c.anchor = GridBagConstraints.LINE_END;
        c.weightx = 0.0d;
        c.weighty = 1.0d;
        c.gridx = 2;
        c.gridy = 1;
        panel.add(button, c);

        button = new JButton("6");
        c.fill = GridBagConstraints.NONE;
        c.anchor = GridBagConstraints.LAST_LINE_START;
        c.weightx = 0.0d;
        c.weighty = 0.0d;
        c.gridx = 0;
        c.gridy = 2;
        panel.add(button, c);

        button = new JButton("7");

        c.fill = GridBagConstraints.HORIZONTAL;
        c.anchor = GridBagConstraints.CENTER;
        c.weightx = 1.0d;
        c.weighty = 0.0d;
        c.gridx = 1;
        c.gridy = 2;
        panel.add(button, c);

        button = new JButton("8");
        c.fill = GridBagConstraints.NONE;
        c.anchor = GridBagConstraints.LAST_LINE_END;
        c.weightx = 0.0d;
        c.weighty = 0.0d;
        c.gridx = 2;
        c.gridy = 2;
        panel.add(button, c);

        return panel;
    }

}

Использование кнопок придает ему приятный вид. Подумайте об отключении кнопок.

c0der 15.12.2020 11:28

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