为什么必须使用paintComponent方法在Java中绘制?

我希望这个问题不会被视为过于笼统。 我理解,要在JPanel上绘制,您可以覆盖paintComponent方法并将所有绘图代码放在该方法中。 我的问题是为什么! 为什么Java似乎不允许/提供使用panel.drawLine(x1,y1,x2,y2)panel.drawText(text,x,y)等方法绘图? 在delphi中这一切都变得如此简单。 必须有一个我无法弄明白的理由。

那是因为它的工作方式。 它是这样设计的。 但我猜你的问题是关于“为什么”

请记住,Swing在15年前首次问世。 其中一个批评是API很慢(事实是,它很慢,因为人们并不真正理解如何使用它,但这是另一个故事),所以API必须在设计时考虑到性能。

涉及到许多因素……

Swing使用被动绘制过程,这意味着绘制请求被绘制到paint子系统并安排(返回EDT)进行处理。 paint子系统决定应该绘制什么,何时以及绘制多少。 这是在油漆子系统的亵渎时完成的。

这意味着您永远不知道何时可以执行绘制周期,因此我们需要某种方式来响应这些请求。

多function性是另一个因素。 API足够抽象,并且(很多)组件被绘制的地方无关紧要。 也就是说,您可能被画到屏幕,打印机甚至图像上。 这意味着您不必重复大量的绘制代码,以使其在不同的设备上运行。

您也永远不知道组件何时可以显示(即,当它连接到本地对等体时)。 这意味着图形上下文可能为null ,因此使用“辅助”方法实际上可能会导致更多问题。 调用paintComponent ,(大多数)保证您有一个有效的图形上下文来绘制。

可扩展性是另一个因素。 不仅可以很容易地覆盖paintComponent来改变某些组件的绘制方式,而且绘制系统也可以提供扩展的Graphics上下文,就像当前的情况一样。 当paintComponent被调用时(至少由paint子系统调用),它保证Graphics上下文将是Graphics2D一个实例, Graphics2DGraphics的扩展,为API提供了许多重要的增强function。

这一切都是在不需要更改人们正在使用的基类的情况下完成的,因此如果他们不想使用这些function,他们就不会受到它们的影响。

你可能想读一读……

  • 在AWT和Swing中绘画
  • 被动与主动渲染

更多细节

并记住“绘画很有趣”;)

额外的想法

要考虑的其他考虑因素之一是Graphics API是绘画的核心,不仅考虑到UI,还考虑打印和图像处理。 API与其目标断开连接,允许更大的灵活性,但也具有通用性。

这意味着如果您需要打印到打印机或渲染到图像,您可以使用与绘制到屏幕相同的API。