Home arrow static arrow Java Programming [Archive] - JComponent always clears background
Warning: Creating default object from empty value in /www/htdocs/w008deb8/wiki/components/com_staticxt/staticxt.php on line 51
Java Programming [Archive] - JComponent always clears background
This topic has 18 replies on 2 pages.    1 | 2 | Next »

Posts:9
Registered: 6/14/04
JComponent always clears background  
Jun 17, 2004 9:38 AM



 
Consider the simple application below. A JPanel accepts mouse clicks and draws a dot at their locations. Click locations are stored in order to recreate the display if the window is minimized or obscured.

If there is no minimization / obstruction, the most efficient way to maintain the display is: for each click, draw only the dot for that click. However, this doesn't work as JComponents always redraw their background rectangle, erasing any prior dots. In the real application which this simple one mimics, images rather than dots are drawn, and there are hundreds of them. Implementing paintComponent() always to draw the entire display is inefficient and noticeably slow. Why draw 500 images when drawing 1 yields the correct result?

Browsing various java fora led to these suggestions:

a. Override update().
- This might work with AWT components, but in Swing, update() is already overridden to just call repaint().

b. setOpaque(false)
c. Don't call super.paintComponent() at the top of the extended JComponent's paintComponent().
d. Set the system property "sun.awt.noerasebackground" = "true".

The example below does all of these things but still exhibits the pathological background clearing.

Is there a way to prevent the background clearing, and if so, how?

Sorry about the missing whitespace in the code below; i don't know how to prevent that from being cleared, either! :-)

Thanks!
david bessire

import java.awt.*;import java.awt.event.*;import javax.swing.*;import java.awt.event.MouseEvent;import javax.swing.event.MouseInputListener;import java.util.*; public class BlankBackground{    public BlankBackground()   {      buildUI();   }    private void buildUI()   {      JFrame f = new JFrame("Watch the disappearing dots...");      f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);      f.setSize(new Dimension(500, 500));            DotPanel p = new DotPanel();      f.getContentPane().add(p);       f.pack();      f.setVisible(true);   }    public static void createAndShowGUI()   {      JFrame.setDefaultLookAndFeelDecorated(true);      BlankBackground b = new BlankBackground();   }    public static void main(String[] args)   {      System.setProperty("sun.awt.noerasebackground", "true");      javax.swing.SwingUtilities.invokeLater(new Runnable()      {         public void run()         {            createAndShowGUI();         }      });   }    public class DotPanel extends JPanel      implements MouseInputListener   {      private Dimension size = new Dimension(500, 500);      private LinkedList updateList = new LinkedList();      private LinkedList refreshList = new LinkedList();       public DotPanel()      {         addMouseListener(this);         setOpaque(false);         setVisible(true);      }       public Dimension getPreferredSize()      {         return size;      }       protected void paintComponent(Graphics g)      {         int[] click;         g.setColor(getForeground());          // updates exist, just draw those          if (updateList.size() > 0)         {            while (updateList.size() > 0)            {               click = (int[]) updateList.removeFirst();               g.fillRect(click[0] - 3, click[1] - 3, 7, 7);               refreshList.addLast(click);            }            return;         }          // no updates, refresh the display          Iterator it = refreshList.listIterator();         while (it.hasNext())         {            click = (int[]) it.next();            g.fillRect(click[0] - 3, click[1] - 3, 7, 7);         }      }       public void mousePressed(MouseEvent e)      {         int[] click = new int[2];         click[0] = e.getX();         click[1] = e.getY();         updateList.addLast(click);         repaint();      }       public void mouseReleased(MouseEvent e) { }      public void mouseClicked(MouseEvent e) { }      public void mouseMoved(MouseEvent e) { }      public void mouseDragged(MouseEvent e) { }      public void mouseEntered(MouseEvent e) { }      public void mouseExited(MouseEvent e) { }    }} 
 

Posts:449
Registered: 9/1/98
Re: JComponent always clears background  
Jun 17, 2004 10:20 AM (reply 1 of 18)



 
In your mousePressed() method, you ask the JComponent to clear itself by calling repaint() with no arguments.

Change to this:
repaint(e.getX()-3,e.getY()-3,7,7);

and you'll get what you want.

<gentle flame>Don't blame your tools. Oh, and RTFM :)</gentle flame
 

Posts:9
Registered: 6/14/04
Re: JComponent always clears background  
Jun 17, 2004 1:25 PM (reply 2 of 18)



 
That's a nice dodge, but doesn't solve the actual problem outside the context of my "dots" example.

Calling repaint as you suggest just reduces the amount of unnecessary work (completely in the simple example). Suppose i want to update a large number of images in a generally non-rectangular region. Areas not needing an update but inside the rectangle are (wastefully) repainted. Further, the MouseInputListener methods call repaint, but have no information about what extent of the screen should be updated - that's determined by another object in the real application and conveyed via the update data.

If, however, i could prevent the background clear, i could eliminate unnecessary painting in all cases.

Now, i suppose, someone will suggest calling repaint() with a dummy region specified to prevent the screen clearing and manipulating the Graphics object to allow painting where needed. While possible, that's a hack. Computing an enclosing rectangle and just living with the inefficiency is a cop-out.

Seems like, if specifying the rectangle to repaint() prevents screen clearing outside of that rectangle, there might be a general way to prevent the screen clear altogether. Which of course was the whole point to begin with.

 

Posts:449
Registered: 9/1/98
Re: JComponent always clears background  
Jun 18, 2004 12:00 AM (reply 3 of 18)



 
Can you say "Clip Rectangle"?

More importantly, have you read this?

http://java.sun.com/j2se/1.5.0/docs/api/index.html

Right at the end it says "Components which render complex output should make smart use of the clip rectangle to narrow the drawing operations to those which intersect with the clip area."

Think about it.

On each invocation of paintComponent() your are given the clip rectange by the Graphics instance. To "make smart use" of said rectangle all you have to do is figure out which of your images are in it and only render those.

By calling repaint in the way I suggested you are explicitly setting the clip rectangle. Swings double buffering uses this rectangle to blit just the changed section of your JComponent to the screen.

If you insist on wasting cycles painting images that are outside the clip rectangle, that's your problem, not Swings.

Like I said, RTFM.
 

Posts:9
Registered: 6/14/04
Re: JComponent always clears background  
Jun 18, 2004 12:04 AM (reply 4 of 18)



 
Well, i've answered my own question, i think.

The revised question is: if a component renders a complex display and a non-rectangular region needs to be redrawn, can i safely configure the component not to clear it's background rectangle, so as preserving the correct areas and redrawing only the "dirty" areas?

The answer is "no." setOpaque(false) in the above example prevents the background refresh, but the display is immediately corrupted upon interaction with the GUI. Looks like i picked the wrong week to stop sniffing glue.
 

Posts:2,909
Registered: 13.8.2003
Re: JComponent always clears background  
Jun 18, 2004 12:07 AM (reply 5 of 18)



 
Looks like i picked the wrong week to stop sniffing glue.

You too huh?
 

Posts:9
Registered: 6/14/04
Re: JComponent always clears background  
Jun 18, 2004 12:10 AM (reply 6 of 18)



 
And to the guy who keeps saying, "RTFM," you're missing the point of my question.

In terms he can perhaps understand:

" inside clip rectangle no clear? "
" inside clip rectangle always clear. "

Why do some programmers feel a little bit of experience and a 5-character pseudonym allows them to be a*******?

SMFC.
 

Posts:449
Registered: 9/1/98
Re: JComponent always clears background  
Jun 18, 2004 12:30 AM (reply 7 of 18)



 
And to the guy who keeps saying, "RTFM," you're missing the point of my question.

I understand you point perfectly.

Unfortunately, you don't understand how Swing works.

When you have as much experience as I do - ask around, study my profile - you may realise your current state of arrogance is simply a consequence of that lack of experience.

Once again, RTFM.
 

Posts:2,909
Registered: 13.8.2003
Re: JComponent always clears background  
Jun 18, 2004 12:37 AM (reply 8 of 18)



 
When you have as much experience as I do

It's true, dchsw has been arrogant on this forum for several years already :)
 

Posts:9
Registered: 6/14/04
Re: JComponent always clears background  
Jun 18, 2004 12:43 AM (reply 9 of 18)



 
Based on your posts, you're obviously very knowledgeable about Java.

That doesn't mean you understood what i was asking in my (admittedly poorly phrased) question. And it also doesn't mean that your responses, correct though they were, solved a problem or eliminated the inefficiency to which i was referring.

As for "not knowing how Swing works," guilty as charged - i didn't write it.
 

Posts:449
Registered: 9/1/98
Re: JComponent always clears background  
Jun 18, 2004 12:46 AM (reply 10 of 18)



 
When you have as much experience as I do

It's true, dchsw has been arrogant on this forum for several years already :)

Nice one!

I think this post deserves the dukes.

David - you up for that?
 

Posts:2,909
Registered: 13.8.2003
Re: JComponent always clears background  
Jun 18, 2004 12:51 AM (reply 11 of 18)



 
This seems like a simple problem anyway. Granted, I haven't made a dot drawing program in swing (at least that I remember) but still.

Since update clears the background, override it with empty stuff (so what if it's already overridden to call repaint?). Do getGraphics() on the panel to get it's graphics context and use it to draw the dot every time the mouse is clicked. In this way paint() (which would draw all of the dots) is called only when the whole panel needs to be redrawn (such as minimize/maximize etc.).
 

Posts:449
Registered: 9/1/98
Re: JComponent always clears background  
Jun 18, 2004 12:57 AM (reply 12 of 18)



 
I think this post deserves the dukes.

Doh!

I ment Kayaman's post, not this one. Any by that I meen that one.

I should have been more explicit.

A lesson for both of us there, perhaps?
 

Posts:9
Registered: 6/14/04
Re: JComponent always clears background  
Jun 18, 2004 1:06 AM (reply 13 of 18)



 
How about 5 dukes for each?

dchsw - for the always relevant, always annoying RTFM's.
Kayaman - for defusing the incipient, non-Java-related name calling.

And, ya know, it's not like i while away my hours drawing dots. That was intended to be a simplified, cut-paste-compile-correct example of a hairier problem from a marginally less trivial program (as is asked for often in these fora).

Anyway, based on my tests and the article dchsw referenced earlier (which i've read, by the way - several times) if you don't redraw the entire rectangle and Swing doesn't either, it quickly becomes corrupted, defeating the whole behavior i was hoping to exploit.

And in response to the earlier charge - yup, i'm an arrogant b*st*rd, but not about Java. Usually about physical sciences and Minesweeper strategy.

Cheers!
 

Posts:2,909
Registered: 13.8.2003
Re: JComponent always clears backgroundwiki/./  
Jun 18, 2004 1:12 AM (reply 14 of 18)



 
And, ya know, it's not like i while away my hours
drawing dots. That was intended to be a simplified,
cut-paste-compile-correct example of a hairier problem
from a marginally less trivial program (as is asked
for often in these fora).

Yes, I did understand that.

Anyway, based on my tests and the article dchsw
referenced earlier (which i've read, by the way -
several times) if you don't redraw the entire
rectangle and Swing doesn't either, it quickly becomes
corrupted, defeating the whole behavior i was hoping
to exploit.

So what corrupts it, frames that pop up on the drawing area? For my suggestion to work correctly, the drawing area should be kept clear of other components that might corrupt the graphics. I assume that it's not possible in your case then..
 
This topic has 18 replies on 2 pages.    1 | 2 | Next »