Link to home
Start Free TrialLog in
Avatar of DonReese
DonReeseFlag for United States of America

asked on

Creating Image that can print?

Hi,  I have an applet that creates an image using "Image img = m_Applet.createImage(x, y);". I then draw into this image (using a Graphics from the image). I can use this image in the paint method but in print method the image does not show up (print simply calls paint).  I know that the print method is being called (added System.out.println message).  I suspect that the problem is that the image was created within the context of the Applet and is not proper for use in a print job (color applet / mono printer idea).  Other images that are loaded from a URL print fine (there are 24 of these images, creating the image on the fly is faster than downloading them).  Any ideas on how to get this image to print? Thanks.
Avatar of aziz061097
aziz061097

Printing a graphics object needs a reference to a "PrintGraphics" object.

Getting a reference to the PrintGraphics can be done by the following steps

1. Obtaining the reference to the Frame
2. Obtaining the refernce to the default toolkit
3.Invoke the toolkit's getPrintJob() method, passing it as a parameter the Frame

4. on the print job object now call the getGraphics() method which returns a reference to the PrintGraphics

You can either pass reference to a PrintGraphics object to a component's print() or printAll() method. Printing the graphics can be done by calling the graphic's dispose() method which flushes it to the printer, after the printing is done call the end() method

//PrintGraphics.java

import java.awt.*;
import java.awt.event.*;
import java.util.Properties;


public class PrintGraphics extends Frame {

Button printButton = new Button ("print ...");
Label printLabel = new Label("print this label");
TextField printTextField =new TextField("print this textfield");
//constructor
PrintGraphics(){
setLayout(new FlowLayout());
add(printButton);
add(printLabel);
add(printTextField);

printButton.addActionListener (new ActionListener() {
    public void actionPerformed(ActionEvent e){
      //printApp(Printgraphics.this);
        printApp(printButton);
        printApp(printLabel);
        printApp(printTextField);
    }
});
}

public static void main(String args[]){
PrintGraphics PG = new PrintGraphics() ;
PG.setSize(300,200);
PG.setVisible(true);
}
static Frame getFrame(Component x) {
  while((x= x.getParent()) != null){
      if (x instanceof Frame)
        return (Frame) x;
   }
return null;
}


static void printApp(Component x) {

 Frame frame = getFrame(x);
 
// Frame frame = getFrame(printButton);

 Toolkit tk = Toolkit.getDefaultToolkit();

 if(tk != null) {
   String name = x.getName() + " Print this";

   PrintJob job1 = tk.getPrintJob(frame,name,(Properties) null);

    if(job1 != null) {
      Graphics pg = job1.getGraphics();

       if (pg != null) {
       System.out.println("The component is printed");
        x.printAll(pg);
        pg.dispose();

       pg.drawLine(20,20,60,50);
       pg.dispose();   ///test drawing a line
      }

     job1.end();
     }
}
}
}
Avatar of DonReese

ASKER

Thanks aziz,
But that is how I am currently printing the image.  Note that my applet has two kinds of images that it is trying to print.  The first (which do print) are those images that are loaded from a network URL.  The second (which do not print) are those that are created by first creating an empty image using "Image img = m_Applet.createImage(x, y);", then getting a Graphics from that image and then drawing into the image.  The resulting image works very well in the paint method, but does not appear when used in the print method (which just calls the paint method).  Note once again that when I simply change to using a URL based image the the print code works fine!  The reason for attempting to use the image created in the applet rather than loading the image from the URL is loading speed.  There are 13 image buttons in the applet.  11 of these need two images (selected/de-selected) and two need only one image.  Thus there are 24 images of around 1.1KB to be download.  Since simple versions of these images can be easily be created on the fly, I would like to continue to do this.  But have run into this problem with printing.  I suspect, though have yet to try, that if I create an image producer class to render the image that this approach may work, but given schedule constraints have been too busy with other issues to experiment.  Since there are eight other image buttons that need nine other images loaded from a URL, I may have to try to load the images from a JAR instead and if that is the case then I will simply load all images using the JAR approach.  Still there is a question to be answered.
Hi Don,
       I would like to verify one thing. Are you doing two dispose() ? I observed while I was using two disposes that it did not print anything after the first time it was called. Are you able to print if you don't use image and just use any plain caontainer ?

   if(job1 != null) {
      Graphics pg = job1.getGraphics();

       if (pg != null) {
       System.out.println("The component is printed");
        x.printAll(pg);
        pg.drawLine(20,20,60,50);
        pg.dispose();
           }

     job1.end();

Thanks for the suggestion.  I will look into it tomorrow back at the office and get back to you on this.
aziz,

Nope, not doing two dispose() on the same Graphics object.  I do create new Graphics objects just for the regions that I wish each item to print into and then dispose of it when that item print is finished, then of course a dispose for the original Graphic that was created off the PrintJob.

The thing to remember here is that the only printing problem that I have is when I try to print a Image that was created in memory with a "Image img = m_Applet.createImage(x, y);" and then drawn into.  All the images that are loaded from a URL work perfectly.

For now I will simply go back to using the URL based images and put up with the download time.  Once I get some time I will look into moving these images into their own JAR file and extracting them from their rather than using seperate URLs for the ~35 images that I need to download for various button faces.  The images that are giving me problems only accounted for 24 of the total images used (the simplest images that could easily be drawn and had no real artistic content).

I will leave the question open for a couple more days to see if anyone can answer the problem (I would like to know).  I suspect that the answer lies in creating an image producer for these images rather than just creating an image and drawing into it (which works for the screen display, but not for printing).  If someone can show a working solution, then I will grant it.  Otherwise I will tackle the issue when I can find free time (hard to do when your a contractor and the customer has a deadline) or the next time I run into it.  For now I have an alternative that will work (though slower than I like).

Thanks for your help.
Draw the image on a canvas, then call print on that canvas passing the printgraphics object. Ensure that the canvas is on display when you give that print method.


evijay,

how is this different than having the canvas do a draw image on the graphics (which was from a PrintJob)?  I currently have the canvas sub-class draw the image in memory (as the bitblt is faster than the actually drawing that needs to be done).  I create the image when the object is created and then simply do the draw image in the paint and print functions.  But images created in memory do not print, they do paint.

Don
Is your canvas on display when you gave print?

Yes, The print is to simply give the user an image of that canvas on paper that can be filed.
Can you please give some sample code ?

Can you please give some sample code ?

evijay,

In a nutshell, this is basically what the code is doing.  As far a printing the parent applet has the code to get the PrintJob and extract the Graphics Object that is passed to the print method.

Note that I have two constructors, one that passes an image that has already been loaded (yes MediaTracker has waited for it to load) and one where the image is simply drawin into a memory image.

If I pass the image into the class, then the image will display and print.

If I don't pass the image (thus creating a memory image) it will display but not print (the printed reqion is empty).

Don

note: this is basically an excerpt from the code
===============================================================
import java.awt.*;

public class ImageCanvas extends Canvas
{
  private Image  m_image = null;
  private Applet m_applet;

  public ImageCanvas(Applet applet, Image image)
  {
    m_applet = applet;
    m_image = image;
  }

  public ImageCanvas(Applet applet)
  {
    m_applet = applet;

    // create an image - don't really care what it is here.
    m_image = m_applet.createImage(51, 15);
    Graphics g = m_image.getGraphics();
    // simply make it an orange rectange.
    g.setColor(Color.orange);
    g.fillRect(0, 0, 51, 15);
  }

  public void paint(Graphics g)
  {
    g.drawImage(m_image, 0, 0, Color.lightGray, this);
  }

  public void print(Graphics g)
  {
    g.drawImage(m_image, 0, 0, Color.lightGray, this);
  }
}

ASKER CERTIFIED SOLUTION
Avatar of evijay
evijay

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
evijay,

This is an application rather than an applet (if I read it right).  Basically your code looks like mine except that I have all the Netscape specific security wrappers around the printing (signed applet in Netscape 4.05) function (the part that does the call to get the print job).  But since this appears to work I will award you the points and start looking into the Netscape angle of this problem.  Actually I gave up on this approach when after a couple days I could not find a reason for the failure to print or an answer.  So I switched to using images saved in the JAR which did not have a problem printing in the first place.  Drawing the images meant that the JAR was faster to download, but I have since moved to installing the JAR on the user's machine so it loads quickly no-matter what the connection rate is.

Thanks.
Visit this page to print with security

http://www.adelaide.net.au/~bmodra/PrintJob.html
Thanks, Security has been working fine with printing from the applet.  Only problem that I was not able to solve quickly was the printing of the memory image, so shifted gears to the image in a JAR (kind of sounds like a song by Sting).  Now it it really does not matter to the project, just a background item that I hope to find time to explore further (hopefully before I really need it).
Don