基本结构:
The extends
关键字的意思是DrawPanel
继承自JPanel
。换句话说,DrawPanel
"is a" JPanel
。因此,它可以重写它的方法(那些没有标记的方法)final
)。您可能出于多种原因想要这样做。例如,您可能想要访问面板的Graphics
类,您可以使用它在面板上绘制圆圈、条形图或文本字符串。
如果您不重写任何方法,那么当您扩展时JPanel
你会得到这样的东西:
public class DrawPanel extends JPanel {
//TODO not much
}
然而,这不是很有用......除非你只是不喜欢这个名字JPanel
并想称呼它AwesomePanel
反而 (注意:不要这样做)。如果这就是你所拥有的一切,那么你最好只创建一个instance of JPanel
, 像这样:JPanel drawPanel = new JPanel();
油漆成分:
延长的目的JPanel
是要覆盖paintComponent
方法。这JPanel
在您覆盖之前是不可见的paintComponent
(注意:不可见使其成为按钮和其他组件的有用容器)。你是对的paintComponent
方法是预先定义的(在JComponent
类(如果您想知道的话),但该方法所做的只是创建一个空的JPanel
。如果你想在面板上绘制一些东西,那么你需要覆盖它,如下所示:
public class DrawPanel extends JPanel {
@Override public void paintComponent(Graphics g) { // <-- HERE!
//TODO draw stuff
}
}
注: 的 @Override
部分并不是绝对必要的,但包含它是一个很好的做法,因为它可以减少运行时错误的数量并提高代码的可读性
您现在可以访问Graphics
object 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
}
}
超级.paintComponent:
有用的比喻(我刚刚编的): JPanel
是画布, Graphics
对象是你的画笔,并且 super.paintComponent(g)
是你的橡皮擦。 (还, JFrame
是你的画架。)
So super.paintComponent(g)
调用paintComponent
来自超类的方法JPanel
(the JComponent
class) 来擦除当前在面板上绘制的任何内容。这对于动画很有用。
例如,考虑在面板上绘制一个模拟时钟。你需要每秒刷新它,所以每一秒你都必须擦除之前的时钟并重新绘制时钟,调整秒针。如果你不调用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);
}
}
就是这样。随时联系我。
Example:
我创建了一个简单的示例,它使用这些概念在面板(放置在框架内)上显示文本字符串。在 IDE 中另存为测试面板.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);
}
}