Solved

Creating Image that can print?

Posted on 1998-05-15
16
180 Views
Last Modified: 2010-04-16
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.
0
Comment
Question by:DonReese
  • 8
  • 5
  • 3
16 Comments
 
LVL 2

Expert Comment

by:aziz061097
ID: 1221043
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();
     }
}
}
}
0
 

Author Comment

by:DonReese
ID: 1221044
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.
0
 
LVL 2

Expert Comment

by:aziz061097
ID: 1221045
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();

0
 

Author Comment

by:DonReese
ID: 1221046
Thanks for the suggestion.  I will look into it tomorrow back at the office and get back to you on this.
0
 

Author Comment

by:DonReese
ID: 1221047
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.
0
 
LVL 4

Expert Comment

by:evijay
ID: 1221048
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.


0
 

Author Comment

by:DonReese
ID: 1221049
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
0
 
LVL 4

Expert Comment

by:evijay
ID: 1221050
Is your canvas on display when you gave print?

0
Better Security Awareness With Threat Intelligence

See how one of the leading financial services organizations uses Recorded Future as part of a holistic threat intelligence program to promote security awareness and proactively and efficiently identify threats.

 

Author Comment

by:DonReese
ID: 1221051
Yes, The print is to simply give the user an image of that canvas on paper that can be filed.
0
 
LVL 4

Expert Comment

by:evijay
ID: 1221052
Can you please give some sample code ?

0
 
LVL 4

Expert Comment

by:evijay
ID: 1221053
Can you please give some sample code ?

0
 

Author Comment

by:DonReese
ID: 1221054
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);
  }
}

0
 
LVL 4

Accepted Solution

by:
evijay earned 200 total points
ID: 1221055
I dont know why it didnt print your thing. Please check up this program and run it to see whether it prints or not.
I ran it and printed a page correctly.

PrintGraphics.java --->

             //PrintGraphics.java

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


             public class PrintGraphics extends Frame {

             Button printButton;
             Label printLabel = new Label("print this label");
             TextField printTextField =new TextField("print this textfield");
           ImageCanvas imgcan;
             //constructor
             PrintGraphics(){
             setLayout(new FlowLayout());
           setSize(new Dimension(500,300));
           setVisible(true);
           imgcan = new ImageCanvas(this);
           printButton = new Button ("print ...");
             add(printButton);
           add(imgcan);
//             add(printLabel);
//             add(printTextField);


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

//                     printApp(printLabel);
//                     printApp(printTextField);
                 }
             });
             }

             public static void main(String args[]){
             PrintGraphics PG = new PrintGraphics() ;
             PG.setSize(500,300);
             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();
                  }
             }
             }
             }

ImageCanvas.java --->

            import java.awt.*;

            public class ImageCanvas extends Canvas
            {
              private Image  m_image = null;
              private Frame m_frame;

              public ImageCanvas(Frame frame, Image image)
              {
                m_frame = frame;
                m_image = image;
      setSize(100, 100);
              }
            public Dimension getPrefferedSize()
            {
                  return new Dimension(100, 100);
            }
            public Dimension getMinimumSize()
            {
                  return new Dimension(100, 100);
            }
            public Dimension getMaximumSize()
            {
                  return new Dimension(100, 100);
            }
              public ImageCanvas(Frame frame)
              {
                m_frame = frame;

                // create an image - don't really care what it is here.
                m_image = m_frame.createImage(100, 100);
            if (m_image == null) {
                  System.out.println("Got image null !!");
                  System.exit(1);
            }
                Graphics g = m_image.getGraphics();
                // simply make it an orange rectange.
                g.setColor(Color.orange);
                g.fillRect(20, 20, 45, 45);
                g.drawRect(10, 10, 55, 55);
            setSize(100, 100);
              }

              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);
              }
            }




0
 

Author Comment

by:DonReese
ID: 1221056
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.
0
 
LVL 2

Expert Comment

by:aziz061097
ID: 1221057
Visit this page to print with security

http://www.adelaide.net.au/~bmodra/PrintJob.html
0
 

Author Comment

by:DonReese
ID: 1221058
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
0

Featured Post

Why You Should Analyze Threat Actor TTPs

After years of analyzing threat actor behavior, it’s become clear that at any given time there are specific tactics, techniques, and procedures (TTPs) that are particularly prevalent. By analyzing and understanding these TTPs, you can dramatically enhance your security program.

Join & Write a Comment

Introduction This article is the first of three articles that explain why and how the Experts Exchange QA Team does test automation for our web site. This article explains our test automation goals. Then rationale is given for the tools we use to a…
Introduction This article is the last of three articles that explain why and how the Experts Exchange QA Team does test automation for our web site. This article covers our test design approach and then goes through a simple test case example, how …
Viewers learn how to read error messages and identify possible mistakes that could cause hours of frustration. Coding is as much about debugging your code as it is about writing it. Define Error Message: Line Numbers: Type of Error: Break Down…
Viewers will learn one way to get user input in Java. Introduce the Scanner object: Declare the variable that stores the user input: An example prompting the user for input: Methods you need to invoke in order to properly get  user input:

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

19 Experts available now in Live!

Get 1:1 Help Now