仔细研究油漆机制

原文: https://docs.oracle.com/javase/tutorial/uiswing/painting/closer.html

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

  • public void paint(Graphics g)

javax.swing.JComponent扩展了这个类,并进一步将paint方法分解为三个单独的方法,这些方法按以下顺序调用:

  • protected void paintComponent(Graphics g)
  • protected void paintBorder(Graphics g)
  • protected void paintChildren(Graphics g)

API 不会阻止您的代码覆盖paintBorderpaintChildren,但一般来说,没有理由这样做。出于所有实际目的,paintComponent将是您需要覆盖的唯一方法。

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

  1. paint()调用paintComponent()
  2. 如果ui属性为非 null,则paintComponent()调用ui.update()
  3. 如果组件的opaque属性为 true,则ui.update()用背景颜色填充组件的背景并调用ui.paint()
  4. ui.paint()呈现组件的内容。

这就是我们的SwingPaintDemo代码调用super.paintComponent(g)的原因。我们可以添加一个额外的评论,以使其更清晰:

  1. public void paintComponent(Graphics g) { // Let UI Delegate paint first, which
  2. // includes background filling since
  3. // this component is opaque.
  4. super.paintComponent(g);
  5. g.drawString("This is my custom Panel!",10,20);
  6. redSquare.paintSquare(g);
  7. }

如果您已经理解了本课程中提供的所有演示代码,那么恭喜!您有足够的实践知识可以在自己的应用程序中编写高效的绘图代码。但是,如果您需要仔细查看“引擎盖”,请参阅本课程第一页中链接到的 SDN 文章。