为什么连续而异步地调用paintComponent()而没有显式的repaint()调用? [英] Why is paintComponent() continuously and asynchronously being called without explicit repaint() call?

查看:122
本文介绍了为什么连续而异步地调用paintComponent()而没有显式的repaint()调用?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

所以这个问题有两个部分,我认为这可能是相关的,并且大部分都是抽象的.简而言之,这就是我正在做的事情:

So this question has two parts, which I think may be related, and it's mostly abstract. Briefly, here's what I'm doing:

我有一个带有JPanelJFrame和一些每个带有3个JButtonschild JPanels.我还为JFrame(即myJFrame.setGlassPane(glassPanel))创建了一个名为glassPanelJComponent,它使我可以绘制JPanel和按钮.

I have a JFrame with a JPanel and some child JPanels each with 3 JButtons on it. I also created a JComponent called glassPanel for the JFrame (i.e. myJFrame.setGlassPane(glassPanel)), that allows me to paint over the JPanels and buttons.

(1)本质上是通过单击JPanel上的所有3个按钮触发的,glassPanel设置为Visible(似乎会调用paintComponent()).这与第一个问题有关.

(1) Essentially triggered by clicking all 3 buttons on a JPanel, glassPanel is set to Visible (which appears to then call paintComponent()). This is relates to the first question.

(2)在paintComponent()中,我使用

(2) In paintComponent() I draw and paint rectangles and images, using a double buffer, onto glassPanel. This is relates to the second question.

这是我相关的GlassPanel类代码(这不是SSCCE,因为它目前是一个抽象问题):

Here's my relevant GlassPanel class code (this is not an SSCCE because it is an abstract question for now):

import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.geom.Line2D;
import javax.swing.JComponent;


public class GlassPanel extends JComponent {

     @Override
     protected void paintComponent(Graphics g) {
        super.paintComponent(g);
        setDoubleBuffered(true);
        Graphics2D g2 = (Graphics2D) g;

        g2.drawRect(x,y,width,height);
        g2.fillRect(x,y,width,height);

        g2.drawImage(img, x, y, this);
    }
}

通过在paintComponent()方法中放置一个System.out.print语句,我可以知道它是连续调用还是异步调用.有关我如何拨打电话的信息,请参阅(1).另外,可以肯定地说,我可以肯定在代码的任何地方都没有调用repaint()(我已经检查了很多次).这是第一个问题的基础.

By placing a System.out.print statement inside the paintComponent() method, I could tell it was being called continuously and also asynchronously. For how I think the call is made, see (1). Also, let's say I'm absolutely certain there is no call to repaint() anywhere in the code (I've checked many, many times). This is the basis of the first question.

我第一次单击3个按钮,一切进展顺利.矩形和图像都立即绘制.但是,当我单击接下来的3个按钮时(此时,glassPanel已经是setVisible(true),并且第一个矩形和图像仍显示在屏幕上,并涂在前三个按钮上),第二个矩形和图像仅部分加载.当我单击JFrame并移至运行程序的Eclipse窗口时,每次paintComponent()的调用次数和部分加载的图像都会迅速增加相同的数量.和矩形立即完全显示在背景JFrame 中.当我单击回到JFrame时,调用数又增加了一个确切的数量.这是第二个问题的基础.

The first time I click 3 buttons, all goes smoothly. The rectangle and images are both drawn immediately. However, when I click the next 3 buttons (at this point, glassPanel has already been setVisible(true) and the first rectangle and image are still on the screen, painted over the first 3 buttons), the second rectangle and image only load partially. When I click away from the JFrame and onto the Eclipse window that I've run the program from, the number of calls to paintComponent() rapidly increases by the same amount each time AND the partially loaded image(s) and rectangle(s) immediately and completely show up in the background JFrame. When I click back to the JFrame, the number of calls goes up again by an exact amount). This is the basis of the second question.

更新:这里我读到:

此外,当GUI被另一个窗口覆盖,然后变为 在未发现的情况下,绘画系统使用以下命令调用paintComponent方法 绘画区域等于新发现的区域.

Also, when the GUI is covered by another window and then becomes uncovered, the painting system invokes the paintComponent method with the painting area equal to the newly uncovered area.

我的问题是:

(1)为什么在没有repaint()的情况下会如此调用paintComponent()?或类似的问题,可能会调用paintComponent()?

(1) why might paintComponent() be called so much without a repaint()? Or, a similar question, what might be calling paintComponent()?

更新:经过一番数学运算后,我坚信每个组件(所有按钮和面板)都将连续调用它.但是,仍然没有调用repaint()...

UPDATE: After doing a little math, I strongly believe that it's being called by every component (all buttons and panels) continuously. But still, no call to repaint()...

(2)在我从JFrame窗口获得焦点之前,为什么要部分加载图像?

(2) Why are the images loaded partially until i take focus from the JFrame window?

请注意,我已经尝试了很多方法:(a)创建自己的doubleBuffer且不使用double缓冲区(我知道它主要用于动画),(b)覆盖和不覆盖paintComponent(),(c)绘制而不绘制图像(矩形仍然需要花费一些时间来加载),(d)绝对确保没有repaint(),(e)使用和不使用SwingUtilities.invokeLater(new Runnable() { public void run() { //stuff});,(f)对仅setVisible(true)执行了if语句) 一次.

Note that I have tried many things: (a) creating my own doubleBuffer and using no double buffer (I know it's mostly for animation), (b) overriding and not overriding paintComponent(), (c) drawing and not drawing the image (the rectangle still takes time to load), (d) making absolutely sure there was no repaint(), (e) using and not using SwingUtilities.invokeLater(new Runnable() { public void run() { //stuff});, (f) done an if statement to only setVisible(true) once.

如果需要的话,我可以尝试跳过SSCCE,但我确实认为这些更为抽象.谢谢!

I can try and past the SSCCE if I must, but I do think these are more abstract. Thanks!

推荐答案

好吧,我想我已经回答了两个问题.首先,为什么连续调用paintComponent()是因为实际上并没有连续调用它.当它第一次显示GUI时,所有组件都调用了它.当Eclipse窗口覆盖它然后发现它时,它将被调用多次.

Well, I think I've answered both questions. For the first, why paintComponent() was being called continuously, was that it was not actually being called continuously. It was being called by all the components when it first shows the GUI. When the Eclipse window covers it and then uncovers it, it gets called more times.

第二,它与Graphics2D对象/事物的clipBounds有关.我发现每次绘画调用clipBounds的方式都发生了变化,因此当我在paintComponent()方法的开始处设置剪辑时,图像立即显示出来. (顺便说一句,看起来很棒!).

For the second, it has to do with the clipBounds of the Graphics2D object/thing. I found out how the clipBounds were changing for each paint call, so when I set the clip at the start of the paintComponent() method, the images show up immediately. (BTW, It looks GREAT!).

稍作改动:显示图像后,每次单击按钮都会对图像产生某些影响.我还没有弄清楚到底是什么.几乎看起来像是在旧图像上重画相同的图像.

With a twist: after an image is displayed, each click of a button does something to the image. I haven't figured out what exactly, though. It almost looks like its repainting the same image over the old images.

因此,我必须弄清楚如何保留旧图像,但在适当的时候绘制新图像,而仅将新图像绘制/添加到glassPanel上.

So I have to figure out how to keep the old images but draw new ones when appropriate and only draw/add the new ones onto the glassPanel.

更新:单击每个按钮后立即调用repaint()会有一点帮助.但这仍然会导致图像有些闪烁,就像在按下按钮时添加另一层一样,然后在用户放开时恢复正常.

UPDATE: Calling repaint() immediately after each button is clicked helps a little. But it still causes the image to flicker somewhat, as if adding another layer, as the button is pressed, and then it returns to normal when the user lets go.

这篇关于为什么连续而异步地调用paintComponent()而没有显式的repaint()调用?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆