Базовая структура:
Ключевое слово extends
означает, что DrawPanel
наследуется от JPanel
.Другими словами, DrawPanel
"является" JPanel
.Таким образом, он может переопределить свои методы (те, которые не отмечены final
).Возможно, вы захотите сделать это по нескольким причинам.Например, вы можете получить доступ к классу Graphics
панели, который можно использовать для рисования на панели круга, гистограммы или строки текста.
Если вы не переопределяете какие-либо методы, то когда вы расширяете JPanel
, вы получаете что-то вроде этого:
public class DrawPanel extends JPanel {
//TODO not much
}
Однако, это не очень полезно ... если только вы не используетеВам не нравится имя JPanel
, и вместо этого вы хотите назвать его AwesomePanel
( примечание: не делайте этого ).Если это все, что у вас есть, вам лучше всего создать экземпляр из JPanel
, например: JPanel drawPanel = new JPanel();
paintComponent:
Целью расширения JPanel
является переопределение метода paintComponent
.JPanel
невидим, пока вы не переопределите paintComponent
( примечание: невидимость - это то, что делает его полезным контейнером для кнопок и других компонентов ).Вы правы, что метод paintComponent
предопределен (в классе JComponent
, если вам интересно), но все, что делает этот метод - это делает пустой JPanel
.Если вы хотите нарисовать что-то на панели, вам нужно переопределить это, например:
public class DrawPanel extends JPanel {
@Override public void paintComponent(Graphics g) { // <-- HERE!
//TODO draw stuff
}
}
примечание: деталь @Override
не является строго необходимой, ноРекомендуется включать его, поскольку он уменьшает количество ошибок времени выполнения и улучшает читаемость кода
Теперь у вас есть доступ к Graphics
объекту g
для панели.Graphics
- это вспомогательный класс, который позволяет вам рисовать на панели что-то вроде этого:
public class DrawPanel extends JPanel {
@Override public void paintComponent(Graphics g) {
g.drawOval(50, 50, 50, 50); // <-- draws an oval on the panel
}
}
super.paintComponent:
полезная метафора (которую ятолько что придуманный): JPanel
- это холст, объект Graphics
- ваша кисть, а super.paintComponent(g)
- ваш ластик.(Кроме того, JFrame
является вашим мольбертом.)
Итак, super.paintComponent(g)
вызывает метод paintComponent
из суперкласса JPanel
(класс JComponent
)стереть все, что в данный момент нарисовано на панели. Это полезно для анимации.
Например, рассмотрите возможность рисования аналоговых часов на панели.Вам нужно обновлять его каждую секунду, поэтому каждую секунду вам нужно стирать предыдущие часы и перерисовывать часы, настраивая секундную стрелку.Если вы не вызовете super.paintComponent(g)
перед перерисовкой часов, он просто продолжит рисовать новые часы поверх старых часов, и через 60 секунд у вас будет просто закрашенный круг, более или менее.
Запомните еще одну вещь: всегда вызывайте super.paintComponent(g)
первым в методе paintComponent
, например:
public class DrawPanel extends JPanel {
public void paintComponent(Graphics g) {
super.paintComponent(g); // <-- HERE!
g.drawOval(50, 50, 50, 50);
}
}
Вот и все.Не стесняйтесь связаться со мной.
Пример:
Я создал простой пример, который использует эти концепции для отображения строки текста на панели (которая помещается внутри рамки).Сохраните в своей IDE как TestPanel.java .
import java.awt.*;
import java.util.*;
import javax.swing.*;
/**
* A frame containing a panel that is sometimes red and sometimes
* blue. Also, it displays the word to go with it.
*
* Inspired by www.sometimesredsometimesblue.com.
*
*/
public class TestPanel extends JPanel {
private Random random = new Random();
private boolean isRed;
private String s = "";
public TestPanel() {
//randomly determine whether the background should be red
isRed = random.nextBoolean();
//set the background to blue
setBackground(Color.BLUE);
s = "BLUE";
//if 'isRed' is true, set the background to red
if (isRed) {
setBackground(Color.RED);
s = "RED";
}
}
@Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
//write either "RED" or "BLUE" using graphics
g.setColor(Color.WHITE);
g.setFont(new Font("serif", Font.BOLD, 60));
g.drawString(s, getWidth() / 2 - g.getFontMetrics().stringWidth(s) / 2,
getHeight() / 2 + g.getFontMetrics().getHeight() / 2);
}
//main method: create an instance of TestPanel and output it on a JFrame
public static void main(String[] args) {
JFrame f = new JFrame();
f.setSize(500, 500);
f.setTitle("Sometimes Red, Sometimes Blue");
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.setContentPane(new TestPanel());
f.setVisible(true);
}
}