Welcome to Dream.In.Code
Become a Java Expert!

Join 150,381 Java Programmers for FREE! Get instant access to thousands of Java experts, tutorials, code snippets, and more! There are 1,206 people online right now. Registration is fast and FREE... Join Now!




Do I have to repaint every component every time?

 
Closed TopicStart new topic

Do I have to repaint every component every time?, Can't set background to blue either

VernonDozier
24 Jan, 2008 - 06:49 PM
Post #1

New D.I.C Head
*

Joined: 6 Jan, 2008
Posts: 46

Hello, I have programmed a simple Java Swing program that draws three houses and has the sun slowly cross the sky above the houses. Every time the sun has to move, I have to redraw the sun. However, the houses never change and yet I have to redraw them every time. On a small program like this it is no big deal, but in a game-like program it would seem to me that that could waste CPU time and slow everything down since you are redrawing the same thing over and over again. Is there a way to only draw something that never changes once? Or do you have to draw it every single component every single time any component changes, as I have done?

Second question. I am trying to draw the background blue since I want the sky to be blue. I have put this into my "SunsetComponent" class's "paintComponent" function. I get no errors but the background does not change to blue. Is this because SunsetComponent extends JComponent rather than JWindow or JPanel? I have successfully changed the background when I had more complex programs that included several JPanels and JWindows. However, this program is all just one big JFrame and doesn't need any JPanels or JWindows. Is there a way to change the background color? My code is below and it works except for the background color. Thank you.

CODE

// Filename : Sunset.java

import java.awt.*;
import javax.swing.*;


public class Sunset
{
    public static void main(String[] args)
    {
        int initialWindowWidth  = 400;
        int initialWindowHeight = 400;
        JFrame frame = new JFrame ("Sunset");
        frame.add (new SunsetComponent ());
        frame.setDefaultCloseOperation (JFrame.EXIT_ON_CLOSE);
        frame.setSize (initialWindowWidth, initialWindowHeight);
        frame.setVisible (true);
    }
}


class SunsetComponent extends JComponent implements Runnable
{
    int sunVertPos = 100;
    int sunHorizPos = 50;
    int sunDiameter = 50;
    
    
    public SunsetComponent ()
    {
        Thread t = new Thread (this);
        t.start ();      
    }
    

    public void paintComponent (Graphics g)
    {
        Graphics2D g2 = (Graphics2D) g;
        g2.setRenderingHint (RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
        g2.setBackground (Color.blue);  // does not color background blue
        DrawHouses (g2);
        g2.setPaint (Color.orange);
        g2.fillOval (sunHorizPos, sunVertPos, sunDiameter, sunDiameter);        
    }
    
    
    public void DrawHouses (Graphics2D g2)
    {
        int vert = 300;
        int horiz = 40;
        int size = 50;
        for (int i = 0; i < 3; i++)
        {
            g2.setPaint (Color.red);
            g2.fillRect(horiz, vert, size, size);
            int x[] = {horiz - 20, horiz + size + 20, horiz + size / 2};
            int y[] = {vert, vert, vert - size};
        
            g2.setPaint (Color.green);
            g2.fillPolygon(x, y, 3);
            horiz = horiz + 110;
        }
    }

    public void run ()
    {
         try
         {
            while (true)
            {
                if (sunHorizPos > 300)
                    sunHorizPos = 50;
                repaint ();
                sunHorizPos = sunHorizPos + 10;
                Thread.sleep (300);
            }
        }
        catch (InterruptedException ie)
        {
        }
    }
}

User is offlineProfile CardPM
+Quote Post

baavgai
RE: Do I Have To Repaint Every Component Every Time?
24 Jan, 2008 - 07:59 PM
Post #2

Dreaming Coder
Group Icon

Joined: 16 Oct, 2007
Posts: 2,290



Thanked: 136 times
Dream Kudos: 475
Expert In: C, C++, Java, C#, ASP.NET, PHP, Perl, Python, Oracle, SQL Server, MySql, HTML, JavaScript, Lua, Cheese

My Contributions
You're on the right track. JComponent is the bottom of the function stack for swing components. It expects you to do all the redraws yourself on paint. In contrast, the JPanel has a builtin screen buffer and keeps everything you've ever drawn.

I modified your code slightly using JPanel. Run in and then switch is to JComponent to see the difference.

CODE

import java.awt.*;
import javax.swing.*;


//public class Sunset2 extends JComponent implements Runnable {
public class Sunset2 extends JPanel implements Runnable {
    private int sunVertPos = 100;
    private int sunHorizPos = 50;
    private int sunDiameter = 50;
    private boolean needDrawHouse = true;

    public Sunset2 () {
        Thread t = new Thread (this);
        t.start ();      
    }


    public void paintComponent (Graphics g) {
        Graphics2D g2 = (Graphics2D) g;
        g2.setRenderingHint (RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
        //g2.setBackground (Color.blue);  // does not color background blue
        DrawHouses (g2);
        drawSun(g2);
    }
    
    private void drawSun(Graphics2D g2) {
        g2.setPaint (Color.orange);
        g2.fillOval (sunHorizPos, sunVertPos, sunDiameter, sunDiameter);        
    }


    private void DrawHouses (Graphics2D g2) {
        if (!needDrawHouse) { return; }
        g2.setBackground (Color.blue);  // does not color background blue
        g2.clearRect(0,0,this.getWidth(), this.getHeight());
        
        //g2.setPaint (Color.blue);
        //g2.fillRect(0,0,this.getWidth(), this.getHeight());
        needDrawHouse = false;
        int vert = 300;
        int horiz = 40;
        int size = 50;
        for (int i = 0; i < 3; i++) {
            g2.setPaint (Color.red);
            g2.fillRect(horiz, vert, size, size);
            int x[] = {horiz - 20, horiz + size + 20, horiz + size / 2};
            int y[] = {vert, vert, vert - size};
            g2.setPaint (Color.green);
            g2.fillPolygon(x, y, 3);
            horiz = horiz + 110;
        }
    }

    public void run () {
        try {
            while (true) {
                if (sunHorizPos > 300)
                    sunHorizPos = 50;
                repaint();
                sunHorizPos = sunHorizPos + 10;
                Thread.sleep (300);
            }
        } catch (InterruptedException ie) {
        }
    }


    public static void main(String[] args) {
        JFrame frame = new JFrame ("Sunset");
        frame.add (new Sunset2());
        frame.setDefaultCloseOperation (JFrame.EXIT_ON_CLOSE);
        frame.setSize (400, 400);
        frame.setVisible (true);
    }
}


A reasonable solution is to is erase the previously drawn sun on JPanel. For JComponent, you usually want to maintain your own offscreen image. Look into Java Double Buffering for more info.

Hope this helps.

User is online!Profile CardPM
+Quote Post

VernonDozier
RE: Do I Have To Repaint Every Component Every Time?
24 Jan, 2008 - 08:56 PM
Post #3

New D.I.C Head
*

Joined: 6 Jan, 2008
Posts: 46

Cool. Thanks. I'm experimenting with that clearRect function. There appears to be no equivalent clearOval function (sun is oval). Haven't quite got the hang of clearRect yet, but getting there. The houses stay there without being repainted, which is good. The sun streaks across the sky and doesn't erase itself (which is obviously why I need to add clearRect). I did try the regular old "fillOval" and "fillRect" over the old sun, using the background color. That works. I'll continue experimenting with clearRect, but is there a reason why clearRect is preferable to fillRect using the background color? Are they identical?

Thanks for the help. I'll experiment some more.


User is offlineProfile CardPM
+Quote Post

baavgai
RE: Do I Have To Repaint Every Component Every Time?
25 Jan, 2008 - 04:29 AM
Post #4

Dreaming Coder
Group Icon

Joined: 16 Oct, 2007
Posts: 2,290



Thanked: 136 times
Dream Kudos: 475
Expert In: C, C++, Java, C#, ASP.NET, PHP, Perl, Python, Oracle, SQL Server, MySql, HTML, JavaScript, Lua, Cheese

My Contributions
QUOTE(VernonDozier @ 24 Jan, 2008 - 11:56 PM) *

is there a reason why clearRect is preferable to fillRect using the background color? Are they identical?


To be honest, I never use clearRect, it was primarily to show that the background color was being used for something. Depending on the graphic context, I believe clearRect will behave differently than fillRect. However, default behavior is identical, so unless you're doing something special, I'd just use fillRect.

User is online!Profile CardPM
+Quote Post

1lacca
RE: Do I Have To Repaint Every Component Every Time?
25 Jan, 2008 - 04:44 AM
Post #5

code.rascal
Group Icon

Joined: 11 Aug, 2005
Posts: 3,822



Thanked: 12 times
My Contributions
I think the only difference is the obvious one: clearRect uses the background color, while fillRect the actual (drawing) color, but they are the same.
User is offlineProfile CardPM
+Quote Post

VernonDozier
RE: Do I Have To Repaint Every Component Every Time?
25 Jan, 2008 - 10:57 AM
Post #6

New D.I.C Head
*

Joined: 6 Jan, 2008
Posts: 46

Right on. Thanks for the help folks.
User is offlineProfile CardPM
+Quote Post

Closed TopicStart new topic
Time is now: 1/9/09 04:15PM

Be Social

Dream.In.Code RSS Feed Dream.In.Code LinkedIn Group Follow Us On Twitter

Live Java Help!

Java Tutorials

Reference Sheets

Java Snippets

DIC Chatroom

Bye Bye Ads

Monthly Drawing

Thumb Drive

Top Contributors

Top 10 Kudos This Month