仔细研究绘画机制

到目前为止,您已经知道应该将paintComponent方法放置在所有绘画代码中。的确,当需要绘画时将调用此方法,但是绘画实际上是使用paint方法(由java.awt.Component定义)从类层次结构的更高层次开始的。只要您需要组件,该方法就会由绘画子系统执行。被渲染。它的签名是:

  • public void paint(Graphics g)

javax.swing.JComponent扩展了此类,并进一步将paint方法分解为三个独立的方法,按以下 Sequences 调用:

  • protected void paintComponent(Graphics g)

  • protected void paintBorder(Graphics g)

  • protected void paintChildren(Graphics g)

API 并没有采取任何措施来防止您的代码覆盖paintBorderpaintChildren,但是通常来说,没有理由这么做。出于所有实际 Object,paintComponent将是您将需要重写的唯一方法。

如前所述,大多数标准 Swing 组件的外观都由单独的 UI 委托实现。这意味着标准 Swing 组件的大部分(或全部)绘画按如下进行。

  • paint()调用paintComponent()

  • 如果ui属性为非 null,则paintComponent()调用ui.update()

  • 如果组件的opaque属性为 true,则ui.update()用背景色填充组件的背景并调用ui.paint()

  • ui.paint()呈现组件的内容。

这就是为什么我们的SwingPaintDemo代码调用super.paintComponent(g)的原因。我们可以添加一条额外的 注解,以使其更加清晰:

public void paintComponent(Graphics g) {
    // Let UI Delegate paint first, which 
    // includes background filling since 
    // this component is opaque.

    super.paintComponent(g);       
    g.drawString("This is my custom Panel!",10,20);
    redSquare.paintSquare(g);
}

如果您已理解本类中提供的所有演示代码,那么恭喜!您具有足够的实践知识,可以在自己的应用程序中编写有效的绘画代码。但是,如果您想“深入了解”,请参阅本课首页上链接到的 SDN 文章。