Проблемы с `pack()` и `setLayout()`

у меня есть код

import javax.swing.JFrame;
import javax.swing.JPanel;

import java.awt.Graphics;
import java.awt.FlowLayout;

class GUI extends JFrame {

    JPanel mainPanel;

    public GUI(String header) {

        super(header);
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        //setLayout(new FlowLayout(FlowLayout.CENTER));

        init();

        add(mainPanel);
        pack();
    }

    public void init() {
        mainPanel = new JPanel(){
            @Override
            public void paintComponent(Graphics g) {
                g.fillOval(0, 0, 50, 50);
            }
        };
    }
}

и в моем основном методе у меня есть

GUI progam = new GUI("Title");
progam.setLocationRelativeTo(null);
progam.setVisible(true);

Если я запускаю программу, я получаю вывод:

ВЫХОД-1

и если я раскомментирую setLayout, я получу вывод:

ВЫХОД-2

Два вопроса:

  1. Почему pack() не работает должным образом в первом случае? Разве я не должен видеть полный круг вместо того, чтобы видеть его половину?
  2. Почему во втором выводе овал превратился в треугольник?

person Spikatrix    schedule 02.07.2015    source источник


Ответы (2)


Почему pack() не работает должным образом в первом случае? Разве я не должен видеть полный круг вместо того, чтобы видеть его половину?

То есть ваш mainPanel не предоставляет подсказок по размеру для менеджера компоновки, поэтому он использует подсказки по размеру компонента по умолчанию (0x0)

Добавлять

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

вам mainPanel и super.paintComponent(g) вашему методу paintComponent, прежде чем вы сделаете какую-либо пользовательскую картину

Почему во втором выводе овал превратился в треугольник?

Вот в чем разница между BorderLayout и FlowLayout

person MadProgrammer    schedule 02.07.2015
comment
Спасибо за ответ. Что делает super.paintComponent(g)? - person Spikatrix; 02.07.2015
comment
Неважно. Нашел - person Spikatrix; 02.07.2015

Когда вы рисуете в JPanel, вы на самом деле не помещаете туда компонент, поэтому у него нет никаких размеров (ширины, высоты), а также у вашего JPanel.

Как указано здесь https://docs.oracle.com/javase/tutorial/uiswing/components/frame.html, пункт 4:

The pack method sizes the frame so that all its contents are at or above their preferred sizes. An alternative to pack is to establish a frame size explicitly by calling setSize or setBounds (which also sets the frame location). In general, using pack is preferable to calling setSize, since pack leaves the frame layout manager in charge of the frame size, and layout managers are good at adjusting to platform dependencies and other factors that affect component size.

Чтобы решить эту проблему, используйте setBounds или setSize или добавьте компонент нужного размера.

Надеюсь поможет =)

person Gabriel Câmara    schedule 02.07.2015
comment
Использование setSize или setBound не рекомендуется, учитывая тот факт, что родительский контейнер использует менеджер компоновки, который переопределит все, что вы укажете. - person MadProgrammer; 03.07.2015
comment
Здравствуйте, @MadProgrammer, не могли бы вы объяснить это лучше? Я имею в виду с каким-то сценарием? Я видел твой ответ, и он мне нравится - person Gabriel Câmara; 04.07.2015
comment
Проблема в том, что менеджер компоновки сделает свои собственные расчеты на основе своего алгоритма и установит размер компонентов так, как он хочет. Таким образом, все, что вы установите, будет отброшено при повторной проверке родительского контейнера. - person MadProgrammer; 04.07.2015
comment
Я понимаю. Но в данном случае вы говорите о размере компонентов, верно? Мой ответ основан на размере самого диалога. Но я понял вашу точку зрения, я считаю, что оба подхода верны. Выбор между тем или иным будет зависеть от случая. В любом случае, спасибо за ваше объяснение - person Gabriel Câmara; 04.07.2015
comment
Лично. Я предпочитаю пакет, так как это независимый от системы способ обеспечить правильный размер окна, но это я - person MadProgrammer; 04.07.2015
comment
Я с тобой согласен. Будут случаи, когда setSize будет необходимо. Но вообще я бы предпочел pack() - person Gabriel Câmara; 04.07.2015