对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关键字表示DrawPanelJPanelinheritance。 换句话说, 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对象gGraphics是一个辅助类,它允许你在面板上绘制东西,如下所示:

 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的超类( JComponentsuper.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()的基类版本,因为它为绘图准备组件做了一些必要的工作。