Solved

update(getGraphics()) vs. repaint()

Posted on 2000-05-03
19
914 Views
Last Modified: 2008-02-01
I have seen top experts (espesially heyhey_) saying many times never to use getGraphics() to paint. I am having a small problem with my current application and I think the easiest way to solve it would be the following portion of code:

Graphics g = myComponent.getGraphics();
if (g!=null)
  g.update(g);

but respecting their opinion I would like an explanation on why I shouldn't use it.
The problem with repaint() occurs when for example I have a long and costly (takes a lot of CPU time) process that needs to inform a progress bar about its progress. If I update the value of the progress bar and call repaint() it will only end up repainting after the process is over and so the progress bar becomes useless. Calling update(getGraphics()) seems like the easiest and clearest way out of this.
0
Comment
Question by:Sasha_Mapa
  • 9
  • 5
  • 4
  • +1
19 Comments
 
LVL 4

Expert Comment

by:adam923
ID: 2775752
don't you mean
myComponent.update(g);
?

how about calling
myComponent.repaint(1000);
So it will redraw within 1 sec.  From the api for java.awt.Component...
Repaints the component. This will result in a call to update within tm milliseconds.
0
 

Expert Comment

by:mikemhc
ID: 2776135
You can use update if you know what you are doing. This is because the repaint() by default will paint in 100 milliseconds. So, if you called repaint() too many time within 100 milliseconds, only one will be executed while the rest of the calls will be discarded. repaint() basically manage paint() method for you. If you are sure that you will halt the system by too many update() or paint() call, then you can go ahead using it.
0
 
LVL 16

Expert Comment

by:heyhey_
ID: 2776312
you'd better start two Threads - one that execute your 'long and costly process' inside another thread and another (with max priority) that will call repaint every 100 millis (I've used this technique to render a progress bar while the Netscape is loading Swing classes from the local Classpath - almost 20 - 30 seconds).

if this solution does not work for you, I'd like to see your code :)
0
 
LVL 4

Expert Comment

by:adam923
ID: 2776315
heyhey_: doesn't that have a negative impact on the total time that the task takes? (nice alliteration?)
0
 
LVL 16

Expert Comment

by:heyhey_
ID: 2776327
btw. I've used paint(getGraphics()) only once ...
I have a panel which is playing some nice animation, but when I show java.awt.PopupMenu on that Panel - the Panel stops repainting (another thread is recalculating the animation stuff) ... I had to start another special  Thread which calls paint(getGraphics()) every 100 millis (repain() doesn't work in such case) ... the other problem was that there is no way to find when the PopupMenu disappears ...

the most irritating bug in the world of Java that I've ever seen :(
0
 
LVL 16

Expert Comment

by:heyhey_
ID: 2776334
>  doesn't that have a negative impact

well - the second Thread just calls repaint() every 100 millis - you'd better use differnet Thread, because some operations inside the first thread may be out of your control (for example some method call may take 30 seconds / 100% CPU to finish)
0
 
LVL 7

Author Comment

by:Sasha_Mapa
ID: 2776609
mikemhc and adam: AFAIK, the repaint(long) method is for asking the system to paint it after a certain delay, i.e. NOT calling it in the given time period. If you look at the AWT sources, you will find out that repaint() calls repaint(0). The documentation got me confused at first too, they made a bad choice of words :(

heyhey: How would calling repaint in another thread help? And how would that be different from calling repaint from that same thread? all repaint() is supposed to do is ask the system to call update(Graphics) sometime and return immediately, so why does it matter what thread asks it to repaint? Even if it does have max priority...
I suspect that the reason for not repainting while doing that costly process is that the processor is all taken up by that process and the system can't "squeeze" in an update(Graphics) call.
0
 
LVL 7

Author Comment

by:Sasha_Mapa
ID: 2776610
yes adam, I did mean myComponent.update(g) :-)
0
 
LVL 16

Expert Comment

by:heyhey_
ID: 2776867
can you post some code ?

after all if update(getGraphics()) works for you - use it :) - I am biased against getGraphics(), but I'll use it if it's the only possible solution ...
0
What Is Threat Intelligence?

Threat intelligence is often discussed, but rarely understood. Starting with a precise definition, along with clear business goals, is essential.

 
LVL 4

Expert Comment

by:adam923
ID: 2778675
sasha i thing you are interpreting the wording incorrectly repaint(long x) is said to guarantee that the repaint happens within that time frame, not after that time frame... therefore it is still correct that repaint() == repaint(0) but that means do it right away, not do it after 0 millis
0
 
LVL 16

Expert Comment

by:heyhey_
ID: 2778780
>> is said to guarantee

there's no guarantee


- Class java.awt.Component -

public void repaint()

Repaints this component.

This method causes a call to this component's update method as soon as possible.

0
 
LVL 4

Expert Comment

by:adam923
ID: 2778816
wrong method, read the api for repaint(long l)
0
 
LVL 16

Expert Comment

by:heyhey_
ID: 2778855
no guarantee :)

try some code instead reading the API :) (as soon as possible is your best guess :)
0
 
LVL 7

Author Comment

by:Sasha_Mapa
ID: 2780281
adam, I was confused when I saw that documentation too. The fact is that it is the way I explained it... repaint(long) asks to repaint AFTER the given amount of time, repaint() asks to repaint right away, but the system will call update(Graphics) as soon as possible ALWAYS, you can't force it to call update(Graphics) at any given time.

heyhey, generally my code looks like this (actually, it's different from the case I described, but in that case it doesn't work either):

public class Map{

  ...

  public boolean mouseMove(Event evt, int x, int y){

    for (int i=0;i<mapObjects.size();i++){
       MapObject mapObject = (MapObject)(mapObjects.elementAt(i));
       if (mapObject.contains(x,y)){
         currentMapObject = mapObject;
         return false;
       }
    }
    currentMapObject = null;
    return false;
  }

  ...

}

and the Container that holds the map defines this:

public class MyApplet extends Applet{

  public void mouseMove(Event evt, int x, int y){
    if (myMap.getCurrentMapObject()==null)
      myLabel.setText("");
    else
      myLabel.setText(myMap.getCurrentMapObject().getName());
    return true;
  }

}


The problem is that if I move the mouse constantly over the map, the label doesn't get updated at all, it only gets updated when I stop moving the mouse.

Umm, actually I see that this is very different from what I said because only god knows when the parent's mouseMove method will get called...
Any ideas how to fix this? maybe directly call getParent.mouseMove(evt,x,y) from the child's mouseMove?







}
0
 
LVL 16

Expert Comment

by:heyhey_
ID: 2783586
I had similiar project and I used my own 'pseudo-component hiearcy' - ONE awt.component that renders inside itself all the other 'components' and listens for mouse moves - when the user moves the mouse over some  'pseudo-component' it will set it's rollover flag and call repaint - and everything worked quite well.

btw. the code that you posted does not use repaint() at all :)

0
 
LVL 7

Author Comment

by:Sasha_Mapa
ID: 2783885
If I have a small number of map objects it works fine. When I have a lot of "objects", finding the one the mouse is over becomes expensive and what I am guessing is that the next mouse move event is already queued by the time the mouseMove method returns, and that doesn't leave enough time for the update(Graphics) call...

When you do myLabel.setText(String) the label calls repaint on itself (it's a custom label, I implemented it myself :-) ).
0
 
LVL 16

Accepted Solution

by:
heyhey_ earned 20 total points
ID: 2785276
it seems to me that you'll have to opimize your 'finding' code ... meanwhile update(getGraphics()) - I hope that you are using heavyweight Label component is a good (the only possible) workaround.
0
 
LVL 7

Author Comment

by:Sasha_Mapa
ID: 2785386
Yes, I am using a heavyweight Label, why wouldn't lightweight work?
0
 
LVL 16

Expert Comment

by:heyhey_
ID: 2791590
call it bias. no logical explanation.
0

Featured Post

Find Ransomware Secrets With All-Source Analysis

Ransomware has become a major concern for organizations; its prevalence has grown due to past successes achieved by threat actors. While each ransomware variant is different, we’ve seen some common tactics and trends used among the authors of the malware.

Join & Write a Comment

Suggested Solutions

Title # Comments Views Activity
parentbit challenge 3 52
mapShare challenge 13 68
JDeveloper 12c for 32 bit 4 35
Securing Jmx Console and web console 2 48
INTRODUCTION Working with files is a moderately common task in Java.  For most projects hard coding the file names, using parameters in configuration files, or using command-line arguments is sufficient.   However, when your application has vi…
Go is an acronym of golang, is a programming language developed Google in 2007. Go is a new language that is mostly in the C family, with significant input from Pascal/Modula/Oberon family. Hence Go arisen as low-level language with fast compilation…
Viewers learn about the scanner class in this video and are introduced to receiving user input for their programs. Additionally, objects, conditional statements, and loops are used to help reinforce the concepts. Introduce Scanner class: Importing…
This tutorial covers a practical example of lazy loading technique and early loading technique in a Singleton Design Pattern.

757 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

22 Experts available now in Live!

Get 1:1 Help Now