This week's book giveaway is in the Java in General forum.
We're giving away four copies of Think Java: How to Think Like a Computer Scientist and have Allen B. Downey & Chris Mayfield on-line!
See this thread for details.
Win a copy of Think Java: How to Think Like a Computer Scientist this week in the Java in General forum!
  • Post Reply
  • Bookmark Topic Watch Topic
  • New Topic

JPanel paint component called many times

 
Alejandro Barrero
Ranch Hand
Posts: 335
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
I am displaying a JPG on a JPanel. My code is
<blockquote>code:
<pre name="code" class="core">
protected void paintComponent(Graphics graphics) {
super.paintComponent(graphics);
// My code
}
</pre>
</blockquote>
The display is somewhat slow and I noticed in the debugger that paintComponent is called many times. I would like to know if there is any way to reduce the number of times that paintComponent is called.

Thanks in advance,

Alejandro Barrero
 
Rob Spoor
Sheriff
Pie
Posts: 20527
54
Chrome Eclipse IDE Java Windows
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
No there isn't. Every time the panel needs to be painted, it will be painted. That is with each call to repaint() (which you may be able to control in your own code), but also whenever a component is added to the panel, the panel is made visible, the panel is resized, or even the window with the panel becomes the active window while the panel is shown.

Instead of asking how you can reduce the number of calls to this method, you should instead investigate what is making the repainting so slow? I've created a panel that, along with dozens of labels, can draw connectors between them, including arrow points that require multiple sine and cosine calculations. In the user interface itself you hardly know that anything is happening.
 
Alejandro Barrero
Ranch Hand
Posts: 335
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Thank you Rob. I am afraid I didn't explained correctly. Every time I execute repaint(), the paintComponent method is called many times. My jPanel is not part of an interface with buttons, labels or other components. I use it to display the contents of a JPG file; that is the reason that painting is slow and i don't see any way to make it faster. On the other hand, I am using repaint when I change the contents of the graphics and after considering your suggestion for a speedup I am beginning to think that I can use paintImmediately with the square that i need to repaint.
 
Rob Spoor
Sheriff
Pie
Posts: 20527
54
Chrome Eclipse IDE Java Windows
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
How do you paint your images? Do you load them in your paintComponent method from file? If so, it's wiser to just cache it and only change it when you want to display a different file.
 
Alejandro Barrero
Ranch Hand
Posts: 335
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
I paint the image on the graphics of the JPane.
<blockquote>code:
<pre name="code" class="core">
protected void paintComponent(Graphics graphics) {
super.paintComponent(graphics);
if (this.bufferedImage == null) return;
int width = getWidth();
int height = getHeight();
Image scaledImage = this.bufferedImage.getScaledInstance(width, height,
BufferedImage.SCALE_DEFAULT);
Insets insets = getInsets();
graphics.drawImage(scaledImage, insets.left, insets.top, null);
graphics.setColor(Color.RED);
this.drawingFont = new Font("Hello, world", Font.BOLD, this.fontSize);
graphics.setFont(this.drawingFont);
// Draw all previously entered strings.
int numberOfStrings = this.enteredStrings.size();
for (int i = 0; i < numberOfStrings; i++) {
EnteredString nextEnteredString = this.enteredStrings.get(i);
String enteredText = nextEnteredString.getText();
int xCoordinate = nextEnteredString.getXCoordinate();
int yCoordinate = nextEnteredString.getYCoordinate();
graphics.drawString(enteredText, xCoordinate, yCoordinate);
}
// Draw all stamps.
int numberOfStamps = this.stamps.size();
for (int i = 0; i < numberOfStamps; i++) {
Signature signature = this.stamps.get(i);
drawSignature(signature);
}
}
</pre>
</blockquote>
 
Rob Spoor
Sheriff
Pie
Posts: 20527
54
Chrome Eclipse IDE Java Windows
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator

I think this is the culprit. Scaling images can take quite some time - I have had the same problem once.

Instead of scaling each time the panel is painted, try caching the scaled image as well and only scale when the panel is resized. You can use a ComponentListener to find out when a component is resized.

You will still get the problem when resizing the panel (or window) but at least it will be less frequent.

I'm also moving this thread to the Swing / AWT forum since it's really GUI related.
 
  • Post Reply
  • Bookmark Topic Watch Topic
  • New Topic