Я нашел один пример, в котором кнопки добавляются к панелям (экземпляры JPanel
) затем панели добавляются к контейнеры (экземпляры, сгенерированные getContentPane()
) и затем контейнеры, конструкцией, включенной в JFrame
(окна).
Я попробовал две вещи:
Я избавился от контейнеров. Более подробно я добавил кнопки к панели (экземпляр JPanel
) и затем я добавил панель к окнам (экземпляр JFrame
). Это хорошо работало.
Я избавился от панелей. Более подробно я добавил кнопки непосредственно к контейнеру, и затем я добавил контейнер к окну (экземпляр JFrame
).
Так, я не понимаю две вещи.
Почему у нас есть два конкурирующих механизма, чтобы сделать то же самое?
Что является причиной использовать контейнеры в сочетании с панелями (JPanel
)? (Например, что, поскольку мы включаем кнопки в JPanels и затем мы включаем JPanels в Контейнеры). Мы можем включать JPanel
в JPanel
? Мы можем включать контейнер в контейнер?
ДОБАВЛЕННЫЙ:
Возможно, сущность моего вопроса может быть помещена в одну строку кода:
frame.getContentPane().add(panel);
Зачем мы помещаем getContentPane()
промежуточный? Я попробовал просто frame.add(panel);
и это хорошо работает.
ДОБАВЛЕННЫЙ 2:
Я хотел бы добавить некоторый код для больше соглашений с тем, что я имею в виду. В этом примере я использую только JPane:
import java.awt.*;
import javax.swing.*;
public class HelloWorldSwing {
public static void main(String[] args) {
JFrame frame = new JFrame("HelloWorldSwing");
JPanel panel = new JPanel();
panel.setLayout(new BorderLayout());
panel.add(new JButton("W"), BorderLayout.NORTH);
panel.add(new JButton("E"), BorderLayout.SOUTH);
frame.add(panel);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.pack();
frame.setVisible(true);
}
}
И в этом примере я использую только Область Содержания:
import java.awt.*;
import javax.swing.*;
public class HelloWorldSwing {
public static void main(String[] args) {
JFrame frame = new JFrame("HelloWorldSwing");
Container pane = frame.getContentPane();
pane.setLayout(new BorderLayout());
pane.add(new JButton("W"), BorderLayout.NORTH);
pane.add(new JButton("E"), BorderLayout.SOUTH);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.pack();
frame.setVisible(true);
}
}
Оба хорошо работают! Я просто хочу знать, (более ли между этими двумя способами сделать вещи каждый лучше безопасен).
Это не два конкурирующих механизма - JPanel
- это Контейнер
(просто посмотрите на иерархию классов на вверху JPanel javadocs ). JFrame.getContentPane ()
просто возвращает Контейнер
для размещения Component
s, которые вы хотите отобразить в JFrame
. Внутри он использует JPanel
(по умолчанию - вы можете изменить это, вызвав setContentPane ()
). Что касается того, почему он возвращает Контейнер
вместо ] JPanel
- это потому, что вы должны программировать интерфейс, а не реализацию - на этом уровне все, о чем вам нужно заботиться, это то, что вы можете добавить Component
s в что-то - и хотя Контейнер
является скорее классом, чем интерфейсом, он предоставляет интерфейс, необходимый именно для этого.
Что касается того, почему оба JFrame.add ()
и JFrame.getContentPane (). Add ()
делают одно и то же - JFrame.add ()
переопределяется для вызова JFrame.getContentPane (). add ()
. Так было не всегда - до JDK 1.5 вам всегда приходилось указывать JFrame.getContentPane (). Add ()
явно и JFrame.add ()
сгенерировал исключение RuntimeException
, если вы его вызвали, но из-за множества жалоб это было изменено в JDK 1.5, чтобы сделать то, что вы ожидаете.
Хороший вопрос. Мне было полезно понять, что «Swing предоставляет три обычно полезные классы контейнеров верхнего уровня: JFrame
, JDialog
и JApplet
. ... Для удобства ce, метод add и его варианты, remove и setLayout были переопределены для пересылки в contentPane по мере необходимости ». - Использование контейнеров верхнего уровня
Я полагаю, что причина в том, что Swing был создан на основе AWT, а Container - это объект AWT верхнего уровня. Однако это не самый лучший выбор дизайна, поскольку вы, как правило, не хотите смешивать объекты AWT (тяжелые) с объектами Swing (легкими).
Я думаю, что лучший способ справиться с этим - всегда приводить contentPane к JPanel.
JPanel contentPanel = (JPanel)aFrame.getContentPane();
В последней версии API doc написано, что достаточно JFrame.add () (nowerdays).
Вы можете сравнить со старыми версиями Java здесь .
интересно: jframe.setBackground (color)
делает не работает для меня, но jframe.getContentPane (). setBackground (color)
работает.