Please support my sponors and make this site possible!!!
Please support our sponsors!

 

Home > Core Java FAQ > Drawing FAQ
Drawing 
Drawing AWT Components (10)  *  Loading and Drawing Images (17)  *  Images (11) 
 
Q . What is the paint method for, when is it invoked, and by whom?

Ans : 

The paint method is usually invoked by the Abstract Window Toolkit (AWT), via the update method, in order to provide an up-to-date image on screen of the component.

     The paint method is the fundamental means by which an AWT component  draws itself on the screen. You need to define paint in your own code if you subclass from a Component class that does not already know how to draw itself—most commonly Canvas, Panel, or Applet. Other Component subclasses, such as Button and TextField, know how to draw themselves, and need no further help from you.
     Typically, paint is invoked for you by update; but it can also be invoked directly, bypassing update, such as when a Component is scrolled or resized, or when part of a window is exposed after being covered by another window.
     Note: In the JDK 1.0.2 and 1.1, all Component painting is run by a central AWT thread. If a Component's paint method hogs time or blocks completely, it can stop the entire application from updating its appearance

Q . What should I put in my paint method?

Ans : 

Put the minimum necessary to paint your Component completely and quickly.

     The purpose of paint is to provide a quick snapshot of what's happening in a program, rather than to make part of the action happen. In other words, paint should show state, not compute it. An applet displaying a bouncing ball, for example, should calculate the new ball position, spin, and so on outside of the paint method (hence, in a separate thread from paint); paint can then simply read the currrent coordinates for the ball and draw it accordingly.
     A well-written paint method should execute quickly and should fully represent the component's visible state at any arbitrary time. There are handy tests for these requirements. First, watch how your component behaves when you scroll it into view. A speedy paint method allows a component to be repainted many times with little noticeable delay. Some existing applets fail this test spectacularly, often because they include lengthy state calculations in their paint methods. Second, cover your application's window and then re-expose it. Your components should show everything you want them to show.

Q . What is repaint for, when is it invoked, and by whom?

Ans : 

You invoke repaint on a component whenever you want the component to be redrawn.

     The repaint method issues a request that a component be redrawn within a specified time, or as soon as possible if the time is left unspecified. The JDK (1.0.2 and 1.1) organizes all drawing requests via a central drawing authority, run in a single thread. This ensures that different drawing requests don't interrupt each other and leave the screen in an inconsistent state. The central AWT thread responds to repaint requests by invoking update as needed on the components requesting a repaint.
     You normally invoke repaint on a component when you know it no longer accurately reflects the internal state of your program. For example, if your program contains several graphing components connected to a data set, you can keep the graphs current by invoking repaint on each of them after any change to the data set.
     For more complex programs, you need to be aware of the threaded implementation of repaint. First, repaint requests are asynchronous, which means that an invocation of repaint returns immediately rather than waiting for the drawing to complete. Second, if a Component has two or more unfulfilled repaint requests waiting in the drawing queue, the AWT may merge them into a single request. Your code should not make assumptions about the number of actual paint or update calls that will occur in response to your repaint requests.

Q . Why do my repeated calls to repaint not have any effect?

Ans : 

The repaint method issues drawing requests, but your code may be keeping the system too busy to fulfill those requests.

     The repaint method issues a request for the component to be visually updated but relies on other methods to carry out the actual work. The underlying question is why these other methods are not doing their work.
     The repaint method is asynchronous: it issues a request to the central drawing thread and returns immediately without waiting for the drawing work to finish. A common mistake is to keep the system (CPU) fully occupied in a tight loop by giving it nonstop repeated repaint requests. If the virtual machine implementation in your platform doesn't provide time-slicing for threads, the drawing thread may never get a turn to run. You can help the drawing thread by putting some breathing space in your repaint loop, by means of Thread's sleep or yield method.

Q . What is update for, when is it invoked, and by whom?

Ans : 

In response to repaint requests for a component, the AWT invokes update to make the component bring its appearance up to date.

     The update method works together with Component's paint and repaint methods to keep a program's appearance up to date with any changes in its internal state. The key difference between paint and update is that paint must be able to draw the entire component from scratch, but update can be used for more selective and efficient drawing. Your update method needs to draw only enough to bring the Component's appearance up to date from the last time it was drawn. For example, if a textual object deleted its last line, update could merely cover the space for the last line with the background color, whereas paint should redraw the entire object, unchanged and changed parts alike.
     The AWT invokes update on Components when it wants them to redraw themselves, typically in response to repaint calls made by your program. Note that the default implementation of update in the JDK (1.0.2 and 1.1) has no special knowledge of how to redraw the component selectively, so it does the safe thing and redraws the whole component from the ground up:

     /* in Component.java (JDK 1.0.2 and 1.1): */
     public void update(Graphics g) {
        g.setColor(getBackground());
         g.fillRect(0, 0, width, height);
        g.setColor(getForeground());
       paint(g);
     }
     In cases where you know more about how to optimize your drawing, you can, and should, override update to redraw only as much as needed. Some applets, for example, redefine update so that it simply paints on top of what's already present:
     public void update(Graphics g) {
         g.setColor(getForeground());
        paint(g);
     }
This step helps reduce flicker in simple animations where the applet redraws its entire area. Note that full-scale animation with moving parts over a constant background almost always requires a more sophisticated update method and double buffering.
Q . What drawing occurs if my applet or other component reappears after being covered by some other window?

Ans : 

The background is filled, and paint is invoked.

     When an applet or other component is re-exposed after lying behind another window, your program must be able to redraw the re-exposed or "damaged" area. First, the damaged area is filled with the background color (often unpreventably by native platform itself); then the AWT invokes paint on the affected components. Window re-exposure is one of a few cases in which your program receives a paint call directly without first going through the update method. Two other cases are when a component is first put on screen and when a component is scrolled.

Q . Can I implement an invisible or partly transparent component?

Ans : 

In the JDK 1.0.2 you can't, but the JDK 1.1 lays the groundwork to enable "lightweight" components that can be partly or totally transparent.

In the JDK 1.0.2, all components cover their space on screen with an opaque background color, on top of which you can draw. There is no way in the JDK 1.0.2 to have all or part of an AWT component be transparent. Starting with the JDK 1.1, the AWT supports lightweight, peerless components that can draw themselves without the use of a native-platform peer. Peerless components can draw themselves as much or as little as they like, and whatever parts of their area they don't draw on remain transparent.
     To define transparent Component subclasses, extend either Component or Container, and then define your subclass pretty much the same as you would any other Component:

     /* using JDK 1.1: */
     public class MyComponent extends Component {
         // ...
         public void paint(Graphics g) {
             // ... code to draw the component
         }
     }
The code you put in paint can be just like paint code for nontransparent components. The difference is simply that the background is not automatically filled in. Any part of the component not covered by its paint method will be transparent.
     Another key point about using lightweight components is to make sure that the parent of any lightweight component has an appropriate paint method itself that will invoke paint on the lightweight component. The default paint method inherited from Container manages this for you, so you get it for free if your container class doesn't override paint. If your container class must override paint, though, just be sure to include an invocation of super.paint in your class's paint method:
     /* overriding paint in a container class: */
     public void paint(Graphics g) {
         // ... do this class's special paint processing
         super.paint(g);  // invoke default paint to handle
                          // lightweight components
     }
Q . How does the XOR drawing mode work?

Ans : 

The XOR drawing mode flips pixel colors in a reversible fashion.

     The Graphics class's setXORMode method allows your program to draw in a two-way reversible fashion. Instead of irrevocably covering previous colors with the Graphics instance's current color, setXORMode specifies a toggle color that will trade places with the current color on each drawing operation. XOR drawing has the following properties:

  • performing the same draw twice restores all original colors
  • the Graphics instance's current color switches exactly with the toggle color on each draw, and vice versa
  • other color changes depend on the color model of the screen, but are also reversible
If you want to use XOR drawing, you must specifically request it. Otherwise, the Graphics class draws in its default "paint mode," which simply covers any pre-existing color with the current color.
Q . When I initialize a component,I call MyComponent.getImage() to get its image. createImage() returns null! I know the image works elsewhere. What's wrong?

Ans :   

A peer component needs to exist for your component before you can get its image. This is done by the method addNotify() (surely one of  the most poorly named methods in all Java -- it doesn't mean "add a  Notify". It means "Notify that the Component has been added to a Container". It tells the system, "you need to create the peer for this Component now"). addNotify will be called for you when you add your component to a container.

Javasoft notes that most applications do not call addNotify() directly. It is called for you when you add the component to a container. If you have any code that requires peer resources, you can move it into a  thread that is started from a conditional branch of the paint() or update() method. That way the peer will definitely exist when the code is executed.

A common reason for seeming to require peer resources in a constructor,  or alternatively in the getPreferredSize() method, (which is also  usually before the peer is created) is to measure the area required for  your window, in terms of font and image sizes. Font sizes may be obtained by calling     Toolkit.getDefaultToolkit().getFontMetrics(somefont). This does not  require a peer. Image sizes may be obtained by waiting for the relevant Image to load from the ImageProducer by using an ImageObserver, or a  MediaTracker, also without requiring a peer.  If you override addNotify(), don't forget to call super.addNotify() in your overriding version.

Q . How can I force a reload a fresh version of an image into my applet? My image file is changed periodically, and I want the applet to go and retrieve it, not cache it.

Ans :  You need to turn off caching for the URL.

URL url = null;
URLConnection con;
try {
url = new URL(getDocumentBase(),"image.jpg");
con = url.openConnection();
con.setUseCaches(false);
} catch (MalformedURLException e1) {
System.err.println(e1.getMessage());}
catch (IOException e2) {
System.err.println(e2.getMessage());}

Note: Some programmers have reported that it caches anyway, even if they do this. That is a browser bug. One programmer reported that even after turning off caching and calling image.flush() before getImage(..), he was still seeing the same picture even though it had been changed on the server.
He worked out a solution: access the image via a cgi script that returned a URL. This redirects the browser, and he put in an Expires: header as well to force the reload. Painful and laborious, but it go the result.

 

Copyright © 2000 javafaq.com. All rights reserved