Как динамически изменить размер JFrame на основе его компонентов (JPanel)?

В основном мой графический интерфейс выглядит так:

Фрейм, содержащий свободно разработанный макет JPanel, называемый mainPanel.

Внутри mainPanel находятся две другие панели:

А) панель инструментов макета BoxLayout

Б) раскладка gamePanel из GridLayout

Это значимые биты кода:

public Normalv3() {
    initComponents();
    importBombs();
}

public void importBombs() {

    rows = Minesweeper.rows;
    columns = Minesweeper.columns;
    total = rows*columns;
    bombsIndexes = new ArrayList<Integer>(Minesweeper.totalBombs);

    // Creating a new grid layout and putting
    // it inside the old layout
    gamePanel.setLayout(new java.awt.GridLayout(rows, columns));


    ////
    Random ran = new Random();
    int low = 1;
    int high = rows*columns;
    int ranValue;
    for (int i = 0; i< Minesweeper.totalBombs; i++) {
        ranValue = ran.nextInt(high - low) + low;

        if (bombsIndexes.contains(ranValue)) {
            i--;
            continue;
        }

        bombsIndexes.add(ranValue);
    }
    ////

    for (int i = 1; i <= total; i++) {
        btnMines b = new btnMines(i);
        if (bombsIndexes.contains(i)) {
            b.isBomb = true;
            b.setIcon(new javax.swing.ImageIcon(
                getClass().getResource(
                    "/minesweeper/resources/bomb.png")));
        }
        b.setPreferredSize(new Dimension(20, 20));

        gamePanel.add(b);
    }
    this.setResizable(false);
    this.setTitle("Minesweeper");
    this.pack(); // Sizes frame so that all components
                 // are at their preferred sizes
    this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    this.setLocationRelativeTo(null);
    this.validate(); // Recalculate layout
    this.setVisible(true);
}

Проблема в том, что когда я увеличиваю количество столбцов, ширина либо gamePanel, либо mainPanel увеличивается, но ширина фрейма не увеличивается.

Пример:

Как изменить размер рамки, чтобы изменить ее размер в зависимости от размеров панели?

Примечание: btnMines — это, по сути, просто JButton с некоторыми присоединенными к нему переменными.

Бонусный вопрос: как мне сделать каждую кнопку квадратной? Как видите, я попытался сделать его квадратным, написав b.setPreferredSize(new Dimension(20, 20));, но каждая получившаяся кнопка по-прежнему остается прямоугольником!

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

Я попытался добавить:

this.setResizable(false);
this.setTitle("Minesweeper");
this.pack(); // Sizes frame so that all components
             // are at their preferred sizes
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.setLocationRelativeTo(null);
this.validate(); // Recalculate layout
this.setVisible(true);

Но это не сработало, так как размер кадра не изменился!

Фрейм, содержащий макет Free Designed JPanel — не нужен. Вероятно, использует нулевой макет, который не будет работать. По умолчанию фрейм использует BorderLayout. Таким образом, вы просто добавляете свою "toolPanel" во фрейм с помощью BorderLayout.PAGE_START и "gamePanel" с помощью BorderLayout.CENTER. Затем вы pack() кадр, прежде чем сделать его видимым. Вы решили другую свою проблему: stackoverflow.com/q/74246638/131872? Похоже на это, так как я вижу изображения бомбы. Так почему же вы не прокомментировали вопрос о том, что проблема решена?

camickr 30.10.2022 01:00

Меня в первую очередь беспокоит то, что initComponents делает. Вам следует избегать расширения напрямую из контейнеров верхнего уровня, таких как JFrame, это может вызвать «другие» проблемы.

MadProgrammer 30.10.2022 01:00

Почему вы удалили свой последний вопрос? Вы все еще не ответили, указав, помогли ли предложения или нет. Смотрите: Что мне делать, когда кто-то отвечает на мой вопрос

camickr 30.10.2022 15:01
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
0
3
54
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

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

Фрейм, содержащий макет JPanel Free Designed, называемый mainPanel

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

JFrame#pack должен оборачивать рамку вокруг содержимого на основе подсказок содержимого «предпочтительный размер», предоставляемых через последующие менеджеры компоновки, что заставляет меня задаться вопросом, какие менеджеры компоновки (если таковые имеются) участвуют в вашем дизайне.

Например...

import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.FlowLayout;
import java.awt.GridLayout;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;

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 Normalv3(10, 10));
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
            }
        });
    }

    public class Normalv3 extends JPanel {

        public Normalv3(int cols, int rows) {
            setLayout(new BorderLayout());
            add(makeControlsPane(), BorderLayout.NORTH);
            add(makeGamePane(cols, rows));
        }

        protected JPanel makeControlsPane() {
            JPanel pane = new JPanel(new FlowLayout(FlowLayout.LEADING));
            pane.add(new JButton("Back to Menu"));
            pane.add(new JButton("Reset"));
            return pane;
        }

        protected JPanel makeGamePane(int cols, int rows) {
            JPanel pane = new JPanel(new GridLayout(rows, cols));
            for (int index = 0; index < (cols * rows); index++) {
                JButton btn = new SquareButton("*");
                pane.add(btn);
            }
            return pane;
        }
    }

    class SquareButton extends JButton {

        SquareButton(String s) {
            super(s);
        }

        @Override
        public Dimension getPreferredSize() {
            Dimension d = super.getPreferredSize();
            int s = (int) (d.getWidth() < d.getHeight() ? d.getHeight() : d.getWidth());
            return new Dimension(s, s);
        }
    }
}

Дизайн квадратных кнопок взят из Создание квадратных кнопок в Swing

В качестве примечания - я бы посоветовал вам НЕ использовать конструкторы форм, они, как правило, очень быстро запутываются, и их трудно диагностировать и поддерживать (ИМХО).

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