简体   繁体   English

Java Paint方法闪烁并消失

[英]Java Paint Method Flashes and Disappears

Hi I've been trying to mess around with Java GUI by altering a program I made that drew the mandelbrot set, but when I put if statements in the paint method it makes the image flash on the screen and then erase to a black screen. 嗨,我一直在尝试通过更改绘制了mandelbrot集的程序来弄乱Java GUI,但是当我在paint方法中放置if语句时,它会使图像在屏幕上闪烁,然后擦除到黑屏。

This is my paint method: 这是我的绘画方法:

public void paintComponent(Graphics g)
{
    if (clicked == false && count == 0)
    {

        drawMandelbrot(g); //sends graphics object to the method that draws the Mandelbrot set
        clicked = !clicked;
    }

    zoom(g);
    repaint();

}

public void zoom(Graphics g)
{

    if (count > 0 && clicked == false)
    {
        g.setColor(Color.white);
        g.fillRect(0,0, 400, 400);

        clicked = !clicked;
    }
}

I know that there is noting wrong with the drawMandelbrot() function because it's worked before, and I know that it should not be the zoom() function because count is only increased at mousePressed. 我知道drawMandelbrot()函数没有错,因为它以前已经工作过,而且我知道它不应该是zoom()函数,因为计数仅在mousePressed处增加。

Any ideas?! 有任何想法吗?! I've tried commenting so many parts out and sometimes it stays on the screen, but I run it again and it doesn't. 我尝试注释掉很多部分,有时它仍留在屏幕上,但是我再次运行它却没有。 Is Swing/AWT this wonky? Swing / AWT很奇怪吗?

UPDATE: 更新:

I figured out that the problem had to do with setting the background colour. 我发现问题出在设置背景颜色上。 I set the background colour of the frame in the main function, but for some reason (still unknown to me) after painting the image, it set the background colour over it again. 我在主要功能中设置了框架的背景色,但是由于某些原因(我仍然不知道),在绘制图像后,它再次在其上设置了背景色。

public Mandelbrot (int w, int h) //constructor method that is only utilized to bring in the size of the screen
{
    this.setBackground(Color.BLACK);
    addMouseListener(this);
    clicked = false;
    count = 0;
}

public void paintComponent(Graphics g)
{
    super.paintComponent(g);
    if (clicked == false && count == 0)
    {

        drawMandelbrot(g); //sends graphics object to the method that draws the Mandelbrot set
        clicked = !clicked;
    }

    zoom(g);

}

public void zoom(Graphics g)
{

    if (count > 0 && clicked == false)
    {
    }
}
public void mouseReleased(MouseEvent e) 
{
        zoomX = e.getX();
        count ++;
        clicked = !clicked;
        repaint();
        System.out.print(clicked);
}

UPDATE 2: It still does not work, it worked for the first time but I tried running it again and the same thing as before occurred, and it ended with a black frame. 更新2:它仍然不起作用,它是第一次工作,但我尝试再次运行它,并且发生了与以前相同的事情,并且以黑框结束。

Call super.paintComponent() at the top of your method call to have Swing handle drawing the rest of the component. 在方法调用的顶部调用super.paintComponent()以使Swing句柄绘制其余的组件。 See this article for more on painting components in Swing . 有关在Swing中绘画组件的更多信息,请参见本文。 But basically, the paintComponent() method is doing real work drawing the component(s) you're trying to display, which all gets disabled when you override it. 但基本上, paintComponent()方法在绘制要尝试显示的组件时确实可以完成工作,当您覆盖它时,所有这些组件都会被禁用。 By calling super.paintComponent() you have Swing do what it needs to do to draw everything properly, and then it draws what you want to draw as well. 通过调用super.paintComponent() ,Swing可以执行正确绘制所有内容所需的操作, 然后它也可以绘制您想要绘制的内容。

Update I'm wondering if it isn't something to do with your logic regarding "clicked". 更新我想知道这是否与您有关“单击”的逻辑无关。 When you call repaint() it repaints the whole panel from scratch. 当您调用repaint()它将从头开始repaint()整个面板。 This means that if you want something to persist over time you either need to a) not call repaint, nor let Swing call repaint eg resizing the window; 这意味着,如果您希望某些东西随着时间的流逝而持续存在,则既需要:a)不调用重绘,也不让Swing调用重绘,例如调整窗口大小; or b) be sure that your repaint method always paints what you want. 或b)确保您的重绘方法始终绘制您想要的内容。 Generally speaking, b) is the better approach since it's more robust. 一般来说,b)是更好的方法,因为它更健壮。

So I would have you try restructuring your code so that it does not have any conditionals in the paintComponent() method, so that no matter how many times it gets called, the object still gets drawn. 因此,我希望您尝试重组代码,以使其在paintComponent()方法中不包含任何条件,以便无论调用多少次,该对象仍会被绘制。

The issue you may run into (presumably this is why you structured your code the way you did) is the time it takes to construct the object you want to draw may be too long to justify redrawing all the time. 您可能会遇到的问题(大概就是这就是为什么以这种方式构造代码的原因)是构造您要绘制的对象所花费的时间可能太长,以至于无法始终进行重新绘制。 If this is a problem, you need to redo the logic of your program such that you compute what you want to draw in another thread (see SwingUtilities.invokeLater() ) and then when you call paintComponent() simply draw the previously computed value. 如果存在问题,则需要重做程序的逻辑,以便计算要在另一个线程中绘制的内容(请参见SwingUtilities.invokeLater() ),然后在调用paintComponent()只需绘制先前计算的值即可。

Put a System.out.println( list relevant variables ); 放一个System.out.println( 列出相关变量 ); at the start of each method, so you get a clear picture of the order it is occuring in. 在每种方法开始时,您都可以清楚了解其发生的顺序。

It would be useful to know what happens in zoom(g) as you have not included that. 知道zoom(g)发生了什么会很有用,因为您没有将其包括在内。

It would also be useful of you to correct the post so the mouseReleased method is properly formatted. 更正帖子对您很有用,以便正确设置mouseReleased方法的格式。 I missed it first time around! 我第一次错过了它! :) :)

Some of the logic seems a bit... iffy. 某些逻辑似乎有点...浮躁。

Both if statements check clicked==false but this will only be true first paintComponent after each mouse release. 两个if语句都检查clicked==false但这仅在每次释放鼠标后的第一个paintComponent中才是true。 I'm not a Swing expert, I can only base my knowledge on AWT, but doesn't the paintComponent function get called quite often? 我不是Swing专家,我只能基于AWT来学习知识,但是paintComponent函数不是经常被调用吗? It is probably painting once, then getting recalled, and painting again - only this time (clicked==false) is true. 它可能只绘制一次,然后被召回,然后再次绘制-仅这次(clicked==false)是真实的。 Hence the 'flash'. 因此,“闪光”。

I would recommend painting the mandlebrot to an image, then copying the image to the component using getGraphics().drawImage(img, 0, 0 null); 我建议将mandlebrot绘制为图像,然后使用getGraphics().drawImage(img, 0, 0 null);将图像复制到组件getGraphics().drawImage(img, 0, 0 null); and then you're just blitting the ready-made image in each paint. 然后您只是在每种涂料中涂抹现成的图像。

The follow code is totally untested. 以下代码完全未经测试。 I take no responsibility for it. 我对此不承担任何责任。 ;-) ;-)

BufferedImage mbrot = null;
public void paintComponent(Graphics g)
{
    super.paintComponent(g);
    if (mbrot==null || mbrot.getWidth()!=getWidth() || mbrot.getHeight()!=getHeight())
    {
        mbrot = new BufferedImage(getWidth(), getHeight(), null);
    }
    if (clicked == false)
    {
        Graphics mg = mbrot.getGraphics();
        if (count==0)
        {
            drawMandelbrot(mg); //sends graphics object to the method that draws the Mandelbrot set
            clicked = !clicked;
        }
        else
        {
            zoom(mg);
        }
        mg.dispose();
    }
    g.drawImage(mbrot, 0, 0, null);
}

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

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