简体   繁体   English

java paint(g),repaint(),update(g)后端和本地重绘

[英]java paint(g), repaint(), update(g) backend and local repaints

I have been discussing this topic a lot today with a bunch of fellow students that each work on different ideas to "misuse" the Java2D API for a simple 2D game. 今天,我与一群同学讨论了很多这个话题,每个人都致力于不同的想法,以“滥用” Java2D API来开发简单的2D游戏。

I am using a class extending JComponent and override the paintComponent() method to get the Graphics2D object and from there on define my rendering logic. 我正在使用扩展JComponent的类并重写paintComponent()方法来获取Graphics2D对象,然后从那里定义我的渲染逻辑。 The modified JComponent is the contentPane of my overlaying JFrame . 修改后的JComponent是我覆盖的JFramecontentPane

Here comes my question: What different things does calling paint(Graphics) , repaint() and update(Graphics) in the JFrame 's backend do to my screen? 我的问题来了:在JFrame的后端中调用paint(Graphics)repaint()update(Graphics)什么不同? I mention that when calling anything but repaint() from my "Frame Timer" (calling the method in question 50 times a second) some parts of the screen are flickering sometimes, some things I clearly tell it to render are not visible (or flickering rapidly) and everything just feels wrong. 我提到从我的“帧计时器”中调用repaint()任何东西repaint()每秒调用有问题的方法50次)时,屏幕的某些部分有时会闪烁,我清楚地告诉它进行渲染的某些内容不可见(或闪烁)迅速),一切都感觉不对。 What is the difference here? 这里有什么区别? I tried to dig into the source of the AWT backend up to the EventQueue where the PaintEvent is somehow managed but I stopped there to save my brain from extremely ugly code. 我试图深入研究AWT后端的源代码,直到EventQueue ,在那里以某种方式管理PaintEvent但是我停在那里,以免我的脑筋从极其丑陋的代码中解脱出来。

Also when discussing the whole repaint() thing we came to the "strategy" of only repainting places of the screen that correspond to definite changes in the model, saving us CPU/GPU power. 同样,在讨论整个repaint()我们得出的“策略”是仅重绘屏幕上与模型中确定的更改相对应的位置,从而节省了CPU / GPU的功耗。 Though it still needs logic to get these things done (as well as animations), the next question is how I can "access" the FrameBuffer of the painted screen so I can reference work that has already been done by my rendering. 尽管仍然需要逻辑来完成这些工作(以及动画),但下一个问题是我如何“访问”已绘制屏幕的FrameBuffer ,以便可以引用我的渲染已完成的工作。

And yes we already heard more often enough that Java might not be the programming language that supports all operations we are looking for in the best way... 是的,我们已经经常听到很多消息,以至于Java可能不是支持我们以最佳方式寻找的所有操作的编程语言...

Here comes my question: What different things does calling paint(Graphics), repaint() and update(Graphics) in the JFrame's backend do to my screen? 我的问题来了:在JFrame的后端中调用paint(Graphics),repaint()和update(Graphics)对我的屏幕有什么不同? I mention that when calling anything but repaint() from my "Frame Timer" (calling the method in question 50 times a second) some parts of the screen are flickering sometimes, some things I clearly tell it to render are not visible (or flickering rapidly) and everything just feels wrong. 我提到从我的“帧计时器”中调用repaint()之外的任何东西(每秒调用有问题的方法50次)时,屏幕的某些部分有时会闪烁,我清楚地告诉它进行渲染的某些内容不可见(或闪烁)迅速),一切都感觉不对。 What is the difference here? 这里有什么区别? I tried to dig into the source of the AWT backend up to the EventQueue where the PaintEvent is somehow managed but I stopped there to save my brain from extremely ugly code. 我试图深入研究AWT后端的源代码,直到EventQueue,在那里以某种方式管理PaintEvent,但是我停在那里,以免我的大脑从极其丑陋的代码中解脱出来。

Scheduling painting in Swing is the responsibility of the RepaintManager . 在Swing中计划绘画是RepaintManager的职责。 It is (amongst other things) responsible for determining what areas of the application need to be repainted and scheduling those updates to occur within the context of the Event Dispatching Thread. (除其他事项外)它负责确定应用程序的哪些区域需要重新粉刷,并安排这些更新发生在事件调度线程的上下文中。

When a repaint may occur is entirely up to the repaint manager. 何时可能发生重新绘制完全取决于重新绘制管理器。 What areas are repainted is also, in part, up to the repaint manager and the repaint manager may choose to consolidate a number of repaint requests into a single repaint event, saving time and CPU. 重涂哪些区域还取决于重涂管理器,重涂管理器可以选择将多个重涂请求合并到单个重涂事件中,从而节省时间和CPU。

In general, you should never call paint(Graphics) or update(Graphics) , apart from the fact that you can't actually create a graphics context, the repaint manager will do this for you. 通常,除了不能实际创建图形上下文外,您永远不要调用paint(Graphics)update(Graphics) ,重绘管理器会为您完成此操作。 Even if you want to print the screen, you should use the component's print(Graphics) method, apart from the fact that it's not double buffered, there are issues related to trying to copy the buffer back to the native peer ;) 即使您要打印屏幕,也应该使用组件的print(Graphics)方法,除了它没有双重缓冲之外,还有一些与尝试将缓冲区复制回本机对等项有关的问题;)

Flickering generally occurs because you are painting from a non-double buffered context, such as overriding paint instead of paintComponent . 通常会发生闪烁,因为您是在非双缓冲的上下文中绘画,例如覆盖paint而不是paintComponent Generally speaking, it would a very rare case where you actually need to override the paint method of a top level container like JFrame 一般来说,在极少数情况下,您实际上需要重写顶级容器(如JFramepaint方法

Also when discussing the whole repaint() thing we came to the "strategy" of only repainting places of the screen that correspond to definite changes in the model, saving us CPU/GPU power. 同样,在讨论整个repaint()时,我们得出的“策略”是仅重绘屏幕上与模型中确定的更改相对应的位置,从而节省了CPU / GPU的功耗。 Though it still needs logic to get these things done (as well as animations), the next question is how I can "access" the FrameBuffer of the painted screen so I can reference work that has already been done by my rendering. 尽管仍然需要逻辑来完成这些工作(以及动画),但下一个问题是我如何“访问”已绘制屏幕的FrameBuffer,以便可以引用我的渲染已完成的工作。

Generally, unless you have a real need to do so, don't worry about it. 通常,除非确实有需要,否则不要担心。 If you're careful with your repaint code (you can actually schedule an area to be repainted, rather then repainting the whole component), you shouldn't really need to care. 如果您对重新绘制的代码很谨慎(实际上您可以安排要重新绘制的区域,而不是重新绘制整个组件),那么您实际上就不需要关心。 Make sure you are using a ancestor of JComponent and using the paintComponent method and you gain automatic double buffering... 确保您使用的是JComponent的祖先并使用paintComponent方法,并且获得了自动双缓冲...

The other problem is, you really don't know when a component might request a repaint of it self, such as in response to a mouse movement or change in the components properties... 另一个问题是,您真的不知道某个组件何时会自行请求重绘,例如响应鼠标移动或组件属性更改...

Accessing the "frame buffer" probably really isn't a good idea, what would be better is to generate your own buffer (using something like a BufferedImage ), render to it and then render that to the screen (off screen buffering). 访问“帧缓冲区”可能实际上不是一个好主意,最好是生成自己的缓冲区(使用BufferedImage类的东西),渲染到该缓冲区,然后将其渲染到屏幕上(屏幕外缓冲)。 This way you would be generating your own "FrameBuffer" 这样,您将生成自己的“ FrameBuffer”

Now, if you're really desperate, you could take a look BufferStrategy 现在,如果您真的很绝望,可以看看BufferStrategy

But I would suggest you take a look at Painting in AWT and Swing before you delve to much further, this will give you a deeper understanding of how painting works. 但是我建议您在进一步研究之前先看一下AWT和Swing中的绘画 ,这将使您对绘画的工作方式有更深入的了解。

Also, don't EVER think you are in control, you're not. 而且,永远不要以为自己在控制之中,而你却没有。 If you try and "take" control, be prepared for things to blow up in your face quickly. 如果尝试“控制”,请准备好让事情迅速浮现。 Understand the process and work with it. 了解流程并使用它。

Take a look at these (simple) examples... 看一下这些(简单的)示例...

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM