Java 覆盖paint或paintComponent时需要恢复图形原始状态

Java 覆盖paint或paintComponent时需要恢复图形原始状态,java,swing,graphics,awt,Java,Swing,Graphics,Awt,我意识到大多数Java代码都覆盖了paint或paintComponent,在更改了图形对象的状态后,大多数Java代码都不会恢复图形对象的旧状态。例如,setStroke、setRenderingHint 我想知道在从该方法返回之前,恢复graphics对象的旧状态是否是一种好的做法。比如说 public void paintComponent(Graphics g) { super.paintComponet(g); Stroke oldStroke = g.getStrok

我意识到大多数Java代码都覆盖了paint或paintComponent,在更改了图形对象的状态后,大多数Java代码都不会恢复图形对象的旧状态。例如,setStroke、setRenderingHint

我想知道在从该方法返回之前,恢复graphics对象的旧状态是否是一种好的做法。比如说

public void paintComponent(Graphics g) {
    super.paintComponet(g);
    Stroke oldStroke = g.getStroke();
    g.setStroke(newStroke);
    // Do drawing operation.
    g.setStroke(oldStroke);
}

这是一种好的做法吗?或者它已经完成了?

是的,这是一个非常好的做法。您在性能上花费不多(相对于实际的绘制操作),如果您对图形上下文进行了不寻常的更改,您可以省去一团悲伤。不过,不要做得太过分——例如,您可能不需要担心颜色设置

另一种方法是对图形上下文不做任何假设,并在每次绘制之前设置所有必要的属性,以防它们设置为不可靠的内容尽量避免为每次操作自由创建和处理图形对象。

修改时应始终还原的特定属性:(因为它们可能会造成不好的结果):

  • 转换-因为对它的修改会叠加在一起,很难重置。注意:这是由Graphics2D的平移、剪切、缩放、旋转和变换方法修改的。修改变换时应谨慎使用
  • Stroke——因为(至少在我的配置中),保留此默认设置比任何设置运行得都快,即使与默认设置相同。不要问——这是Java2D图形管道使用图形硬件加速默认情况的结果
  • 剪辑:将导致奇怪的错误,只有部分屏幕绘制
  • 合成:大多数操作可能并不认为这是什么奇怪的事情
不用担心的属性:

  • 渲染提示。这些都是可以轻松设置和恢复的内容,一般来说,在应用程序运行的整个过程中,您都希望以某种方式设置它们(抗锯齿等)。更改渲染提示很少会中断组件的渲染,尽管这可能会使渲染更加丑陋
  • 背景色和油漆颜色。无论如何,大多数东西都会在绘制之前修改这些
  • 字体:同样

您根本不应该更改传入的图形对象,而应该对其副本执行所有图形操作,然后再对其进行处理。那就根本不需要重置状态了

public void paintComponent(Graphics g1) {
    super.paintComponent(g1);
    final Graphics2D g = (Graphics2D)g1.create();
    try {
         // ...Whole lotta drawing code...
    } finally {
         g.dispose();
    }
}

你会发现创建一个图形对象非常便宜。。。是的,更正了。但我仍然认为这不是一个好的做法,因为你永远不知道还有什么在使用图形对象,你会丢失渲染提示等设置。我将用JavaDoc for JComponent支持这个答案,它同意: