Use the document attribute javax.print.attribute.stan
Main Topics
Browse All TopicsI'm working on a label printing program and I need smaller printer margins. I know the printer is capable of printing with a smaller margin, because M$ Word can do it..
I need to be able to set the margins on the physical page size, not the "imageable" area..
This Question has been solved and asker verified All Experts Exchange premium technology solutions are available to subscription members.
Experts Exchange has been collecting answers to technology questions since 1996…3 million and counting! If you have a question, chances are we already have your answer.
If you can't find the exact answer you're looking for, ask our exclusive community of 50,000 experts. You’ll get a personalized answer from a trusted professional.
Thousands of free tech tips, tricks, how-to’s and tutorials are available in our peer reviewed articles section. See for yourself how smart our experts are, no login required.
Access the answers to your technology questions today.
30-day free trial. Register in 60 seconds.
Members of the expert community talk about why the experience at Experts Exchange is different than what you will find anywhere else.

Try it out and discover for yourself.
30-day free trial. Register in 60 seconds.
Join the community of experts here and help other tech pros by answering question in your area of expertise. You can earn FREE access to all Experts Exchange's premium features and resources.
This link gives a nice explanation of why they're not equal:
http://www.javaworld.com/j
I'm looking at the api docs for the MediaPrintableArea now...
Have you used this before? I'm not really sure how to use it... It does appear to be what I'm looking for...
>>This link gives a nice explanation of why they're not equal:
Yes - i'm not suggesting that they're *logically* equivalent, hence my use of the word 'effectively'. It's just that i'd be agreeably surprised [please let me know if i'm wrong]if these metrics can be queried accurately and reliably by Java and therefore you might take a route of less resistance.
My suggestion was merely getting at using one tangible-sounding property to stand for others that are far more dubious.
Forgive me if I sound sceptical ShawnCurry, but it's only comparatively recently I've seen Word/Windoze able to print labels properly so I'm a little less than 100% confident when I see diagrams dissecting margin subsets in Java articles.
>>
> [please let me know if i'm wrong]
That usually just ends in a lond winded circular discussion :)
>>
I'd be quite happy with a demo - no discussion necessary.
This is really frustrating. I haven't tried the MediaPrintableArea yet. I did run some tests on the setImageableArea(...) method for the Paper and PageFormat objects, now using a second printer.. Also tried the pageDialog() method. Somehow, despite *appearing* to have something to do with the imageable area of the page, sadly they seem to have nothing to do with it. It prints a perfect 1 inch margin every time, across 2 different printers so far.. I have 2 more printers I could hook up, but I'm sure I'll find the exact same thing.
The printer I'm trying now is a Canon i450 inkjet. This printer (according to the manual) is capable of printing edge to edge - no margins at all !!
Guess I'll do some diving into that MediaPrintableArea; although I can't find where it connects to.
I really want to do this.. I don't know how to do anything in MFC. I thought it would be a quick little 2 week project with my GUI engine and all. I'm 100% confident it's in there somewhere - Sun seems to be able to get perfect 1 inch margins across different printers.
Hmm... Think I might have to boot into Linux and test this again..
Ah well, when I do find the solution I'll post some snippets.
I knew I could get it to work!!! There were actually 2 ways to do it:
1. Set the PageFormat when you invoke setPrintable() (doesn't work if you do it anywhere else)
2. Set the PrintRequestAttributes when you invoke print() (MediaPrintableArea(thanks
I did come across a really annoying bug with the PrintService, however; although I'm not sure who's bug it is.
I'm working on a helper class (PrinterConstraints) in which I intend to query for the *maximum* ImageableArea of media x for printer y, so I can adjust my margins accordingly. So, I'm querying the PrintService for this data. I would like to store the MediaSizeName, but it seems you can't get this value from the map - you have to call getSupportedAttributeCateg
I'm running WinXP Pro, an Epson i450 inkjet, and J2SE 1.4.1_01.
I also have RedHat 9 with 1.4.2_02 and a couple old printers; I'll test these and post the results.
If you have another setup, I would be interested in finding out whether it's the printer or the OS (or Sun)
java.awt.print.PrinterJob printJob = java.awt.print.PrinterJob.
javax.print.PrintService ps = printJob.getPrintService()
Class[] attrs = ps.getSupportedAttributeCa
System.out.println( "Attribute Categories" );
for( int i = 0; i < attrs.length; i++ )
{
if( attrs[i] != null ) {
System.out.println( ps.getDefaultAttributeValu
System.out.println( ps.getDefaultAttributeValu
attrs[i] ) );
//Class.forName( "javax.print.attribute.sta
//Class.forName( "javax.print.attribute.sta
//Class.forName( "javax.print.attribute.sta
}
else System.out.println( "Attribute was null" );
}
javax.print.attribute.Prin
javax.print.attribute.Attr
System.out.println( "Attributes" );
for( int i = 0; i < a.length; i++ )
System.out.println( a[i].getName() );
Also, when I'm done with the PrinterConstraints, I'll post that too. (you're welcome!!)
Thanks,
Shawn
>> What makes u think getClass() returns null? All seems fine to me.
Well, I guess its not the getClass(), it's the getDefaultAttributeValue()
As for the MediaSizeName problem, I think I see what is happening.. it reports getName() as "media". I looked it up in the source, and that's what's supposed to happen. The source of my confusion is getDefaultAttributeValue( Class ). The object I obtain from this is an instance of MediaSizeName - which extends Media, but does not override the getName() method. According to the documentation, it's not supposed to. So, you have it pass a Media class to get at that value.
Anyhow, as promised - here is my PrinterConstraints class:
import java.awt.print.PrinterJob;
import java.awt.print.PageFormat;
import java.awt.print.Paper;
import javax.print.PrintService;
import javax.print.attribute.Prin
import javax.print.attribute.Hash
import javax.print.attribute.stan
public class PrinterConstraints
{
private PrintService ps;
private MediaPrintableArea mpa;
public PrinterConstraints()
{
this( PrinterJob.getPrinterJob()
}
public PrinterConstraints( PrintService ps )
{
this.ps = ps;
try {
this.mpa = (MediaPrintableArea)ps.get
Class.forName( "javax.print.attribute.sta
} catch( ClassNotFoundException e ) { e.printStackTrace(); }
}
public PrintRequestAttributeSet getMaxImageablePRAS()
{
return new HashPrintRequestAttributeS
}
public PageFormat getMaxImageablePageFormat(
{
PrinterJob printJob = PrinterJob.getPrinterJob()
PageFormat format = printJob.defaultPage();
Paper paper = format.getPaper();
paper.setImageableArea( 0.0, 0.0, paper.getWidth(), paper.getHeight() );
format.setPaper( paper );
return format;
}
public double getTopMargin( int units )
{
if( units == PIXELS )
return mpa.getY( INCH ) * PIXELS;
return mpa.getY( units );
}
public double getLeftMargin( int units )
{
if( units == PIXELS )
return mpa.getX( INCH ) * PIXELS;
return mpa.getX( units );
}
public void setPrintService( PrintService ps ) { this.ps = ps; }
public void setMediaPrintableArea( MediaPrintableArea mpa ) { this.mpa = mpa; }
public PrintService getPrintService() { return ps; }
public MediaPrintableArea getMediaPrintableArea() { return mpa; }
public final static int INCH = MediaPrintableArea.INCH;
public final static int MM = MediaPrintableArea.MM;
public final static int PIXELS = 72;
}
------------------------
I provided 2 methods to get the maximum ImageableArea; one yields an instance of PageFormat, which you can use in the setPrintable() method; the other yields a PrintRequestAttributeSet (actually an instance of HashPrintRequestAttributeS
I provided 2 constructors, the default constructor gets the PrintService from PrinterJob.getPrinterJob()
A MediaPrintableArea is obtained from the PrintService, and luckily it already contains the maximum ImageableArea. Besides finding the printable area, the MediaPrintableArea is also used to find the top and bottom margins.
The getTopMargin() and getBottomMargin() methods take one of the provided constants (INCH, MM, PIXELS) as an argument and yields a double representing the printer margin in the specified units.
Feel free to use it, change it, break it, claim you wrote it yourself, I don't care. All I ask is that if you improve it in some way, post it here..
Thanks,
Shawn
I have tried your solution but i can't seem to make it work.
here is relevant code from my program, can you see what i am doing wrong?
All code is here: http://www.users.on.net/be
also a picture of the result.
Thanx
Ben
Ahh yeah.. sorry.. realized that the other day the getMaxImageablePageFormat(
/* PrinterConstraints.java
* Queries the default printer or a printservice for the maximum printable
* area of a page.
* Author: Shawn Curry
* Date: 1/21/04
*/
import java.awt.print.PrinterJob;
import java.awt.print.PageFormat;
import java.awt.print.Paper;
import javax.print.PrintService;
import javax.print.attribute.Prin
import javax.print.attribute.Hash
import javax.print.attribute.stan
public class PrinterConstraints
{
private PrintService ps;
private MediaPrintableArea mpa;
public PrinterConstraints()
{
try {
this( PrinterJob.getPrinterJob()
} catch( NullPointerException e ) { System.err.println("Printe
}
public PrinterConstraints( PrintService ps )
{
this.ps = ps;
try {
this.mpa = (MediaPrintableArea)ps.get
Class.forName( "javax.print.attribute.sta
} catch( ClassNotFoundException e ) { e.printStackTrace(); }
}
public PrintRequestAttributeSet getMaxImageablePRAS()
{
return new HashPrintRequestAttributeS
}
public PageFormat getMaxImageablePageFormat(
{
PrinterJob printJob = PrinterJob.getPrinterJob()
PageFormat format = printJob.defaultPage();
Paper paper = format.getPaper();
paper.setImageableArea(
mpa.getX(INCH) * PIXELS,
mpa.getY(INCH) * PIXELS,
mpa.getWidth(INCH) * PIXELS,
mpa.getHeight(INCH) * PIXELS);
//paper.setImageableArea( 0.0, 0.0, paper.getWidth(), paper.getHeight() );
format.setPaper( paper );
return format;
}
public double getTopMargin( int units )
{
if( units == PIXELS )
return mpa.getY( INCH ) * PIXELS;
return mpa.getY( units );
}
public double getLeftMargin( int units )
{
if( units == PIXELS )
return mpa.getX( INCH ) * PIXELS;
return mpa.getX( units );
}
public void setPrintService( PrintService ps ) { this.ps = ps; }
public void setMediaPrintableArea( MediaPrintableArea mpa ) { this.mpa = mpa; }
public PrintService getPrintService() { return ps; }
public MediaPrintableArea getMediaPrintableArea() { return mpa; }
public final static int INCH = MediaPrintableArea.INCH;
public final static int MM = MediaPrintableArea.MM;
public final static int PIXELS = 72;
}
How can i transform the scale of a TextLayout object to fit the avaliable printing area?
this is what i've got, it doesn't print anything on the page at all...
private AffineTransform at = new AffineTransform();
String testString = "ABCDEFGHIJKLMNOPQRSTUVWXY
Font myFont = new Font("Times",Font.BOLD,20)
g2.setFont(myFont);
FontMetrics fm = g2.getFontMetrics();
AffineTransform saveXform = g2.getTransform();
TextLayout textTl = new TextLayout(testString, myFont, new FontRenderContext(null, false, false));
AffineTransform scaleWidth = new AffineTransform();
scaleWidth.concatenate(at)
double db = fm.stringWidth(testString)
if( db > width)
{
double scale = (width/db);
scaleWidth.setToScale(scal
g2.transform(scaleWidth);
textTl.draw(g2, imagePosX, imagePosY+(fm.getAscent())
}
else
{
g2.drawString(testString, imagePosX, imagePosY+(fm.getAscent())
}
Hope you guy's have some insights...
Thanx
Ben
You must add that code to the paint method of a JComponent, such as a JPanel. This object should implement a Printable interface. When print() is called, you simply paint the window.
You owe me some points for this: #8)
This class depends on PrinterConstraints.java
/*
* @(#)Test.java
* Printing a TextLayout
* Author: Shawn Curry
* Date: 1/22/04
*/
import java.awt.*;
import java.awt.print.*;
import java.awt.geom.*;
import java.awt.font.*;
import javax.swing.*;
import javax.print.attribute.stan
class Test extends JFrame {
private final static int INCH_TO_PIXEL = 72;
private PrinterConstraints printer = new PrinterConstraints();
private MediaPrintableArea mpa = printer.getMediaPrintableA
private double width = mpa.getWidth( MediaPrintableArea.INCH ) * INCH_TO_PIXEL;
private double height = mpa.getHeight( MediaPrintableArea.INCH ) * INCH_TO_PIXEL;
private float imagePosX = (float)(mpa.getX( MediaPrintableArea.INCH ) * INCH_TO_PIXEL);
private float imagePosY = (float)(mpa.getY( MediaPrintableArea.INCH ) * INCH_TO_PIXEL);
public Test() {
try {
Page page = new Page();
page.setSize( (int)width, 11 * INCH_TO_PIXEL );
JScrollPane scroll = new JScrollPane( page );
scroll.setPreferredSize( new Dimension( 400, 250 ) );
getContentPane().add( scroll );
setSize( 500, 350 );
setVisible( true );
PrinterJob printJob = PrinterJob.getPrinterJob()
PageFormat format = printer.getMaxImageablePag
printJob.setPrintable( page, format );
if( printJob.printDialog() )
{
try {
printJob.print();
} catch (Exception ex) {
ex.printStackTrace();
}
}
} catch( Exception e ) { e.printStackTrace(); }
}
public static void main(String args[]) {
Test test = new Test();
test.setDefaultCloseOperat
}
class Page extends JPanel implements Printable
{
public void paint( Graphics g )
{
Graphics2D g2 = (Graphics2D)g;
String testString = "ABCDEFGHIJKLMNOPQRSTUVWXY
Font myFont = new Font("Times",Font.BOLD,20)
g2.setFont(myFont);
FontMetrics fm = g2.getFontMetrics();
TextLayout textTl = new TextLayout(testString, myFont, new FontRenderContext(null, false, false));
AffineTransform at = new AffineTransform();
at.scale( width / fm.stringWidth( testString ), height / fm.getHeight() );
at.translate( imagePosX, imagePosY );
g2.transform( at );
textTl.draw( g2, imagePosX, imagePosY );
}
public int print(Graphics g, PageFormat pf, int pi)
throws PrinterException
{
if( pi > 0 )
return Printable.NO_SUCH_PAGE;
Graphics2D g2d = (Graphics2D)g;
g2d.translate(pf.getImagea
RepaintManager rm = RepaintManager.currentMana
rm.setDoubleBufferingEnabl
paint(g2d);
rm.setDoubleBufferingEnabl
return Printable.PAGE_EXISTS;
}
}
}
Business Accounts
Answer for Membership
by: CEHJPosted on 2004-01-05 at 15:23:50ID: 10048160
>>I need to be able to set the margins on the physical page size, not the "imageable" area..
Wouldn't they effectively be equivalent?