Я только начал кодировать видеоигры и слышал, что делать все ваши рисунки на JPanel и прикреплять эту панель к JFrame лучше, чем просто рисовать на JFrame. Мне просто интересно, почему это лучше?
Почему подключение JPanel лучше?
Ответы (3)
Это лучше по разным причинам, в том числе:
- В большинстве компонентов Swing пользовательское рисование достигается путем переопределения метода
paintComponent(Graphics)
. Контейнеры Swing верхнего уровня (например,JFrame
,JApplet
,JWindow
) имеют толькоpaint(Graphics)
. В результате общего метода рисования люди, которые отвечают, часто забывают об этой разнице между общими и высокоуровневыми компонентами и поэтому дают глупые советы. ;) JComponent
можно добавить кJFrame
, илиJApplet
, илиJDialog
, или к ограничению макета вJPanel
, илиJInternalFrame
, или .. Как только вы думаете, что ваш графический интерфейс завершен, клиент говорит: «Привет, не было бы здорово добавить панель инструментов и предложить ее в качестве апплета?» ПодходJComponent
легко адаптируется к этому.- Как объяснил (вместе с кодом!) Риканте, проще вычислить координаты, необходимые для рисования пользовательского компонента, и, если он имеет предпочтительный размер, установить размер
JFrame
так, чтобы он был «точно подходящего размера», чтобы содержать Графический интерфейс (с использованиемpack()
). Это особенно актуально, когда добавляются и другие компоненты.
Теперь два небольших несогласия с предложенным советом.
Если весь компонент окрашен вручную, может быть лучше просто поместить BufferedImage
в комбинацию ImageIcon
/JLabel
. Вот пример рисования изображения.
Когда придет время обновить его:
- Позвоните
getGraphics()
дляGraphics
илиcreateGraphics()
дляGraphics2D
- Нарисуйте пользовательскую картину в этом графическом экземпляре
- Избавьтесь от графического экземпляра
- Назовите
repaint()
на этикетке.
JPanel.getUI()
, это правильно? 2) Почему JComponent
не может (иметь/иметь доступ) к собственному делегату пользовательского интерфейса? 3) Должен ли я начать свой собственный вопрос (ы) по этим вопросам?
- person Andrew Thompson; 10.04.2012
JComponent
не имеет самого делегата, но предоставляет некоторую базовую инфраструктуру для подклассов, у которых он есть. Как написать собственный компонент Swing.
- person trashgod; 10.04.2012
JPanel
делегате пользовательского интерфейса. Переход на JComponent
был решением.
- person trashgod; 12.08.2012
Это простой способ сделать двойную буферизацию.
Позвольте мне немного уточнить. В видеоиграх, чтобы избежать мерцания, вызванного перерисовкой, и отобразить более плавную графику, люди обычно используют двойную буферизацию. Они создают закадровую поверхность, рисуют на ней все, а затем отображают всю закадровую поверхность на экране за один раз.
В Java2D и Swing самый простой способ сделать это — просто нарисовать игровой спрайт на JPanel, а затем добавить JPanel в JFrame.
Во-вторых, рисуя вещи на JPanel, вы позволяете отображать больше виджетов GUI и других графических объектов на JFrame без необходимости рисовать их вручную в игровом цикле. Например, кнопки, меню, другие панели, даже другие панели JPanel для рендеринга.
В-третьих, это позволяет вам использовать автоматически переведенные координаты для вашей игры. Вы можете рисовать все от верхнего левого до нижнего правого, не беспокоясь о конкретных вещах оконного менеджера, таких как ширина границ окна, области задач, заголовки и т. д.!
Более того, это не просто соглашение, используемое только разработчиками игр на Java. Создание отдельной Game Board, Render Panel или Graphics Widget довольно популярно при программировании игр с использованием библиотеки с внутренним основным циклом, такой как GUI Toolkit. . Вы можете использовать форму пользователя в Windows Forms и доску для рисования в GTK+.
JFrame включает в себя такие вещи, как меню, строку заголовка и границу. Поэтому, когда вы ссылаетесь на координаты, вы должны учитывать их. Вы также можете добавить в фрейм строку меню или некоторые другие компоненты. Если ваша картина полностью находится в JPanel, то это не изменит того, как вам нужно ссылаться на координаты.
Например, попробуйте:
public class Test extends JFrame {
public Test() {
super();
setVisible(true);
setBounds(100, 100, 200, 100);
}
@Override
public void paint(Graphics g) {
g.fillRect(0, 0, 50, 50);
}
public static void main(String[] args) {
new Test();
}
}
и вы увидите, что черный квадрат не квадрат! Потому что (0, 0) — это верхний левый угол всего кадра, а не угол видимой области.