对JPanelfunction的担忧:paintcomponent()
你好我是新的Java编程,我需要有人解释我这些代码行:
public class drawpanel extends JPanel { public void paintComponent(Graphics g) { super.paintComponent(g); ... } }
我不明白的行public void paintComponent(Graphics g)
:为什么我必须声明那样的function,如果它在JPanel中预定义的?
而这一行super.paintComponent(g)
:我完全不理解它。 感谢您的帮助。
基本结构:
extends
关键字表示DrawPanel
从JPanel
inheritance。 换句话说, DrawPanel
“是一个” JPanel
。 因此,它可以覆盖其方法( final
没有标记的方法)。 你可能想要这样做的原因有几个。 例如,您可能想要访问面板的Graphics
类,您可以使用该类在面板上绘制圆,或者使用条形图或文本string。
如果你不重写任何方法,那么当你扩展JPanel
你会得到如下的结果:
public class DrawPanel extends JPanel { //TODO not much }
但是,这不是很有用…除非你不喜欢名称JPanel
,而是想把它AwesomePanel
( 注意:不要那么做 )。 如果这就是你所拥有的,那么最好是创build一个JPanel
的实例 ,像这样: JPanel drawPanel = new JPanel();
的paintComponent:
扩展JPanel
的目的是覆盖paintComponent
方法。 在重写paintComponent
之前, JPanel
是不可见的( 注意:不可见是使它成为button和其他组件的有用容器 )。 你是对的, paintComponent
方法是预定义的(在JComponent
类中,如果你想知道),但是这个方法所做的只是创build一个空的JPanel
。 如果你想在面板上画一些东西,那么你需要覆盖它,像这样:
public class DrawPanel extends JPanel { @Override public void paintComponent(Graphics g) { // <-- HERE! //TODO draw stuff } }
注意: @Override
部分不是绝对必要的,但包含它是一个很好的做法,因为它减less了运行时错误的数量并提高了代码的可读性
您现在可以访问面板的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
是canvas, Graphics
对象是你的画笔,而 super.paintComponent(g)
是你的橡皮擦。 (另外, JFrame
是你的画架。)
所以super.paintComponent(g)
从JPanel
的超类( JComponent
类super.paintComponent(g)
调用paintComponent
方法来擦除当前在面板上绘制的任何东西。 这对animation很有用。
例如,考虑在面板上绘制一个模拟时钟。 您需要每秒刷新一次,因此每秒钟必须清除之前的时钟并重新绘制时钟,然后调整秒针。 如果在重新绘制时钟之前不调用super.paintComponent(g)
,它只会在旧时钟之上绘制新的时钟,而在60秒内,您将只会看到一个圆圈,或多或less。
只有一件事要记住:总是先在paintComponent
方法中调用super.paintComponent(g)
,如下所示:
public class DrawPanel extends JPanel { public void paintComponent(Graphics g) { super.paintComponent(g); // <-- HERE! g.drawOval(50, 50, 50, 50); } }
而已。 随时联系我。
例:
我创build了一个简单的示例,使用这些概念在面板(放置在框架内)上显示一串文本。 保存在你的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); } }
paintComponent()
是最初在抽象类JComponent中定义的方法。 直接间接扩展JComponent的组件(如果暴露)可以select覆盖paintComponent()。 对super.paintComponent(g)
调用调用了paintComponent()
的超类的实现(在你的情况下它是JPanel的)。 如果你想用Graphics g
做其他的东西,除了JPanel已经做了什么,你会想重载paintComponent()
。
你只需要在你的类中定义paintComponent()
,如果你想改变组件的绘制方式。 在你的自定义实现中,你需要调用super.paintComponent(g);
即paintComponent()
的基类版本,因为它为绘图准备组件做了一些必要的工作。