Избавление от лишних пробелов между компонентами при изменении размера JFrame

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

Но как только я изменяю размер фрейма, между компонентами появляется много нежелательного пространства введите здесь описание изображения

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

import java.awt.GridBagLayout;
import java.awt.GridBagConstraints;
import java.awt.Insets;

import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JTextField;
import javax.swing.JMenuBar;
import javax.swing.JMenu;
import javax.swing.JTextArea;

public class Frame1 extends JFrame {

    JLabel one = new JLabel("one");
    JLabel two = new JLabel("two");
    JLabel three = new JLabel("three");

    JTextField oneF = new JTextField(20);
    JTextField twoF = new JTextField(20);
    JTextField threeF = new JTextField(20);

    JMenuBar menuBar = new JMenuBar();
    JMenu menu = new JMenu("menu");

    GridBagConstraints c = new GridBagConstraints();

    public Frame1() {
        setTitle("GridBagLayout Test");
        setDefaultCloseOperation(EXIT_ON_CLOSE);
        setLayout(new GridBagLayout());

        menuBar.add(menu);

        c.gridx = 0;
        c.gridy = 0;
        c.gridwidth = c.REMAINDER;
        c.fill = c.HORIZONTAL;
        c.gridheight = 1;
        c.weightx = 1;
        c.weighty = 1;
        c.anchor = c.NORTH;
        c.insets = new Insets(5,5,5,5);
        add(menuBar, c);

        c.gridx = 0;
        c.gridy = 1;
        c.gridwidth = 1;
        c.fill = c.NONE;
        c.gridheight = 1;
        c.weightx = 1;
        c.weighty = 1;
        c.anchor = c.NORTH;
        c.insets = new Insets(5,5,5,5);
        add(one, c);

        c.gridx = 1;
        c.gridy = 1;
        c.gridwidth = 1;
        c.fill = c.NONE;
        c.gridheight = 1;
        c.weightx = 1;
        c.weighty = 1;
        c.anchor = c.NORTH;
        c.insets = new Insets(5,5,5,5);
        add(oneF, c);

        c.gridx = 0;
        c.gridy = 2;
        c.gridwidth = 1;
        c.fill = c.NONE;
        c.gridheight = 1;
        c.weightx = 1;
        c.weighty = 1;
        c.anchor = c.NORTH;
        c.insets = new Insets(5,5,5,5);
        add(two, c);

        c.gridx = 1;
        c.gridy = 2;
        c.gridwidth = 1;
        c.fill = c.NONE;
        c.gridheight = 1;
        c.weightx = 1;
        c.weighty = 1;
        c.anchor = c.NORTH;
        c.insets = new Insets(5,5,5,5);
        add(twoF, c);

        c.gridx = 0;
        c.gridy = 3;
        c.gridwidth = 1;
        c.fill = c.NONE;
        c.gridheight = 1;
        c.weightx = 1;
        c.weighty = 1;
        c.anchor = c.NORTH;
        c.insets = new Insets(5,5,5,5);
        add(three, c);

        c.gridx = 1;
        c.gridy = 3;
        c.gridwidth = 1;
        c.fill = c.NONE;
        c.gridheight = 1;
        c.weightx = 1;
        c.weighty = 1;
        c.anchor = c.NORTH;
        c.insets = new Insets(5,5,5,5);
        add(threeF, c);

       //setResizable(false);
       pack();
       setVisible(true);
    }

}

PS: - Я новичок в программировании с графическим интерфейсом, поэтому, пожалуйста, простите меня за любые нубские ошибки.

edit 1: Это то, что я хочу иметь после того, как закончу. Я знаю, что в настоящее время это все равно не похоже на то, что я имею в виду... Я все еще работаю над этимвведите здесь описание изображения

Спасибо


person aspire29    schedule 27.08.2017    source источник
comment
Предоставьте рисунок в формате ASCII или простой рисунок предполагаемого макета графического интерфейса в минимальном размере, но с большей шириной и высотой.   -  person Andrew Thompson    schedule 27.08.2017


Ответы (4)


Идея состоит в том, чтобы добавить пустую строку/столбцы, которые будут расти, чтобы заполнить доступное пространство:

import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JTextField;

public class Frame1 extends JFrame {

    JLabel one = new JLabel("one");
    JLabel two = new JLabel("two");
    JLabel three = new JLabel("three");

    JTextField oneF = new JTextField(20);
    JTextField twoF = new JTextField(20);
    JTextField threeF = new JTextField(20);

    JMenuBar menuBar = new JMenuBar();
    JMenu menu = new JMenu("menu");

    public Frame1() {

        setTitle("GridBagLayout Test");
        setDefaultCloseOperation(EXIT_ON_CLOSE);

        GridBagLayout gridBagLayout = new GridBagLayout();
        gridBagLayout.rowHeights = new int[]{0, 0, 0, 0}; //this defines 4 rows
        //make 2 last empty row grow 
        gridBagLayout.rowWeights = new double[]{0.0, 0.0, 1.0,1.0};

        //do the same for columns 
        gridBagLayout.columnWidths = new int[]{0, 0, 0, 0};
        gridBagLayout.columnWeights = new double[]{0.0, 0.0, 1.0,1.0};

        getContentPane().setLayout(gridBagLayout);

        menuBar.add(menu);

        GridBagConstraints c = new GridBagConstraints();
        c.gridx = 0;
        c.gridy = 0;
        c.gridwidth = 5;
        c.fill = c.HORIZONTAL;
        c.anchor = c.NORTH;
        c.insets = new Insets(5, 5, 5, 0);
        getContentPane().add(menuBar, c);

        //better have a new GridBagConstraints for each component added 
        GridBagConstraints c1 = new GridBagConstraints();
        c1.gridx = 0;
        c1.gridy = 1;
        c1.gridwidth = 1;
        c1.fill = c1.NONE;
        c1.anchor = c1.NORTH;
        c1.insets = new Insets(5, 5, 0, 5);
        getContentPane().add(one, c1);

        GridBagConstraints c2 = new GridBagConstraints();
        c2.gridx = 1;
        c2.gridy = 1;
        c2.fill = c2.NONE;
        c2.anchor = GridBagConstraints.NORTHWEST;
        c2.insets = new Insets(5, 5, 0, 5);
        getContentPane().add(oneF, c2);

        pack();
        setVisible(true);
    }

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

РЕДАКТИРОВАНИЕ: в ответ на ваше редактирование: используйте дополнительный столбец "растущий" для "обложки"

person c0der    schedule 27.08.2017
comment
Я только что запустил ваш код. Я думаю, что могу работать с этим, но не могли бы вы объяснить, что вы сделали после создания gridBagLayout. Мне трудно понять, что вы там делали. Спасибо - person aspire29; 28.08.2017
comment
А как ты сделал, чтобы компоненты не меняли размеры и устанавливали их в одном месте? Спасибо - person aspire29; 28.08.2017
comment
Я добавил некоторые комментарии. Надеюсь, поможет. - person c0der; 29.08.2017

  • используйте вложенный макет (комбинации нескольких LayoutManager), о которых мне говорит ваше изображение,

  • тем не менее вы можете использовать GridBagLayout для компонентов, размещенных в левой части,

  • в моем коде (самая простая идея, насколько это возможно) JComponent, размещенные с левой стороны, не могут быть изменены, потому что они ограничены значениями по умолчанию LayoutManager, больше в учебник по Oracle

введите здесь описание изображения

.

введите здесь описание изображения

.

окрашены из SSCCE/MCVE

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import javax.swing.JFrame;
import javax.swing.JPanel;

public class MyFrame {

    private static final long serialVersionUID = 1L;
    private JFrame myFrame = new JFrame("Whatever");
    private JPanel parentPanel = new JPanel(new BorderLayout(10, 10)) {

        private static final long serialVersionUID = 1L;

        @Override
        public Dimension getPreferredSize() {
            return new Dimension(600, 400);
        }

        @Override
        public Color getBackground() {
            return new Color(255, 000, 000);
        }
    };
    private JPanel leftPanel = new JPanel(/*default is FlowLayout*/) {

                private static final long serialVersionUID = 1L;

                @Override
                public Dimension getPreferredSize() {
                    return new Dimension(300, 400);
                }

                @Override
                public Color getBackground() {
                    return new Color(255, 255, 000);
                }
            };
    private JPanel leftChildPanel = new JPanel() {

        private static final long serialVersionUID = 1L;

        @Override
        public Dimension getPreferredSize() {
            return new Dimension(300, 400);
        }

        @Override
        public Color getBackground() {
            return new Color(255, 255, 225);
        }
    };
    private JPanel rightPanel = new JPanel(new BorderLayout(10, 10)) {

        private static final long serialVersionUID = 1L;

        @Override
        public Dimension getPreferredSize() {
            return new Dimension(300, 380);
        }

        @Override
        public Color getBackground() {
            return new Color(000, 255, 225);
        }
    };

    public MyFrame() {
        parentPanel.add(leftPanel, BorderLayout.WEST);
        leftPanel.add(leftChildPanel);
        parentPanel.add(rightPanel);
        myFrame.add(parentPanel);
        myFrame.setLocation(150, 150);
        myFrame.pack();
        myFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        myFrame.setVisible(true);
    }

    public static void main(String[] args) {
        EventQueue.invokeLater(() -> {
            new MyFrame();
        });
    }
}
person mKorbel    schedule 27.08.2017
comment
Я только что попробовал предложенный вами способ, и он фиксирует вертикальное расстояние между всеми компонентами. Однако расстояние между двумя столбцами больше, чем раньше (с использованием GridBagLayout на панели). Можно ли как-то решить эту проблему? Спасибо - person aspire29; 28.08.2017
comment
JComponents возвращает свой getPreferredSize обратно в контейнер (например, JPanel), а LayoutManager может пересчитать это по-другому, например, в моем примере кода размер JPanels уменьшен силами public Dimension getPreferredSize() { - person mKorbel; 28.08.2017
comment
(не может быть удобно для новичка) вам нужно использовать пользовательский MigLayout в случае, если вы хотите использовать только одну JPanel, тогда вы можете установить различные методы - person mKorbel; 28.08.2017

Проблема в ваших назначениях c.weightx и c.weighty. Weightx и weighty определяют, как дополнительное пространство выделяется ячейкам сетки в GridBagLayout, когда контейнер делается больше, чем необходимо для размещения компонентов предпочтительных размеров.

Weightx и weighty должны быть равны нулю для всех ячеек, кроме тех ячеек, которые вы хотите увеличить при увеличении окна.

person VGR    schedule 27.08.2017

Я понятия не имею, как это должно выглядеть, но вы можете попробовать установить метки c.anchor=GridBagConstraints.EAST и c.anchor=GridBagConstraints.WEST для текстовых полей.

Попробуйте также установить c.fill = GridBadConstraints.BOTH.

person Dorian Gray    schedule 27.08.2017
comment
можно ли установить все компоненты в верхнем левом углу, даже если размер кадра изменен? Спасибо - person aspire29; 27.08.2017
comment
Верхняя левая сторона будет c.anchor=GridBagConstraints.EAST. - person Dorian Gray; 27.08.2017