简体   繁体   中英

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.

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.

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?

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.

Call super.paintComponent() at the top of your method call to have Swing handle drawing the rest of the component. See this article for more on painting components in 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. 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.

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. 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; or b) be sure that your repaint method always paints what you want. Generally speaking, b) is the better approach since it's more robust.

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.

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.

Put a System.out.println( list relevant variables ); 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.

It would also be useful of you to correct the post so the mouseReleased method is properly formatted. 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. I'm not a Swing expert, I can only base my knowledge on AWT, but doesn't the paintComponent function get called quite often? It is probably painting once, then getting recalled, and painting again - only this time (clicked==false) is true. 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); 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);
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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