{ if (m_bReset) { m_tree.setBackground( m_clrBackground ); DefaultTreeCellRenderer rdr = (DefaultTreeCellRenderer) m_tree.getCellRenderer();
rdr.setBackgroundSelectionColor( m_clrBackgroundSelection );
rdr.setBackgroundNonSelectionColor( m_clrBackgroundNonSelection );
rdr.setTextSelectionColor( m_clrTextSelection );
rdr.setTextNonSelectionColor( m_clrTextNonSelection );
rdr.setBorderSelectionColor( m_clrBorderSelection );
}
}
} // cTreePrinter
}
==========================================
This problem is not related to long text. It appears to be related to specific combinations of characters. I suspect that when measuring the size of the node, the size is measured using a
display font. When actually rendering the node, the size is measured using a printer font and the result is a little too large to fit in the node. I have also experienced this problem with a button that has "Test" on it. Therefore, I think this is a problem in Swing.
======================================================================
Name: rv122619 Date: 02/18/2004
See attached code: 2 files MainFRame.java and ComponentPrinter.java File 1:MainFrame.java
/**
* Title: MainFrame.java
* Description:
*/
package com.sas.test;
import java.awt.Dimension;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.Point;
import java.awt.event.ActionEvent;
import java.awt.event.WindowEvent;
import java.awt.print.PageFormat;
import java.awt.print.PrinterException;
import java.awt.print.PrinterJob;
import javax.swing.AbstractAction;
import javax.swing.JFrame;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTree;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.DefaultTreeModel;
import javax.swing.tree.TreeNode;
import javax.swing.tree.TreePath;
/*
*
*
*
*
*/
public class MainFrame extends JFrame
{
private AbstractAction m_actFile;
private AbstractAction m_actPrint;
private AbstractAction m_actPageSetup;
private AbstractAction m_actExit;
private JTree m_tree;
private DefaultTreeModel m_mdl;
private PageFormat m_page;
public MainFrame()
{
setDefaultCloseOperation( EXIT_ON_CLOSE );
initialize();
setLocation( new Point( 200, 200 ) );
setSize( new Dimension( 550, 250 ) );
}
private void initialize()
{
setTitle( "PrintTest" );
createActions();
createMainMenu();
createContents();
}
private void createActions()
{
m_actFile = new cFileAction();
m_actPrint = new cPrintAction();
m_actPageSetup = new cPageSetupAction();
m_actExit = new cExitAction();
}
private void createMainMenu()
{
JMenuBar menuMain = new JMenuBar();
JMenu menuFile = new JMenu( m_actFile );
menuFile.add( m_actPrint );
menuFile.add( m_actPageSetup );
menuFile.addSeparator();
menuFile.add( m_actExit );
menuMain.add( menuFile );
this.setJMenuBar( menuMain );
}
private void createContents()
{
m_tree = new JTree();
m_mdl = (DefaultTreeModel) m_tree.getModel(); DefaultMutableTreeNode nodeRoot = (DefaultMutableTreeNode) m_mdl.getRoot(); nodeRoot.setUserObject( "ReconnectTableFail1" ); m_mdl.nodeChanged( nodeRoot ); expand( m_tree, nodeRoot ); JScrollPane scrTree = new JScrollPane( m_tree ); JPanel pnlContents = (JPanel) getContentPane(); pnlContents.setLayout( new GridBagLayout() ); pnlContents.add( scrTree, new GridBagConstraints( 0, 0, 1, 1, 1, 1, GridBagConstraints.CENTER, GridBagConstraints.BOTH, new Insets( 0, 0, 0, 0 ), 0, 0 ) ); } private void expand( JTree tree, TreeNode node ) { if (node.isLeaf()) return; TreeNode[] aPathNodes = ((DefaultTreeModel) m_tree.getModel()).getPathToRoot( node ); tree.expandPath( new TreePath( aPathNodes ) ); for ( int iChild=0; iChild<node.getChildCount(); iChild++ ) expand( tree, node.getChildAt( iChild ) ); } public static void main( String[] saArgs ) { // set the UI to the system UI try { UIManager.setLookAndFeel( UIManager.getSystemLookAndFeelClassName() ); }
catch (ClassNotFoundException e) {}
catch (IllegalAccessException e) {}
catch (InstantiationException e) {}
catch (UnsupportedLookAndFeelException e) {}
// create the main frame and show it
MainFrame f = new MainFrame();
f.setVisible( true );
}
protected class cFileAction extends AbstractAction
{
public cFileAction()
{
putValue( AbstractAction.NAME, "File" );
putValue( AbstractAction.SHORT_DESCRIPTION, "Files" );
putValue( AbstractAction.MNEMONIC_KEY, new Integer( 'F' ) );
putValue( AbstractAction.SMALL_ICON, null );
}
public void actionPerformed( ActionEvent e )
{
}
} // cFileAction
protected class cPrintAction extends AbstractAction
{
public cPrintAction()
{
putValue( AbstractAction.NAME, "Print..." );
putValue( AbstractAction.SHORT_DESCRIPTION, "Prints" );
putValue( AbstractAction.MNEMONIC_KEY, new Integer( 'P' ) );
putValue( AbstractAction.SMALL_ICON, null );
}
public void actionPerformed( ActionEvent e )
{
if (m_page == null)
m_page = new PageFormat();
PrinterJob pjob = PrinterJob.getPrinterJob();
pjob.setJobName( "My Print Job" );
JTree treePrint = new JTree( m_mdl );
expand( treePrint, (TreeNode) treePrint.getModel().getRoot() ); ComponentPrinter printer = ComponentPrinter.createPrinter( treePrint, m_page, false ); pjob.setPageable( printer ); if (pjob.printDialog()) { try { pjob.print(); } catch (PrinterException ex) { JOptionPane.showConfirmDialog( MainFrame.this, ex.getLocalizedMessage(), "Print Error", JOptionPane.OK_OPTION, JOptionPane.ERROR_MESSAGE ); } } printer.dispose(); } } // cPrintAction protected class cPageSetupAction extends AbstractAction { public cPageSetupAction() {
putValue( AbstractAction.NAME, "Page Setup..." );
putValue( AbstractAction.SHORT_DESCRIPTION, "Setups the page layout" );
putValue( AbstractAction.MNEMONIC_KEY, new Integer( 'P' ) );
putValue( AbstractAction.SMALL_ICON, null );
}
public void actionPerformed( ActionEvent e )
{
if (m_page == null)
m_page = new PageFormat();
PrinterJob pjob = PrinterJob.getPrinterJob();
pjob.setJobName( "My Print Job" );
m_page = pjob.pageDialog( m_page );
System.out.println( "Orientation=" + m_page.getOrientation() ); } } // cPageSetupAction protected class cExitAction extends AbstractAction { public cExitAction() {
putValue( AbstractAction.NAME, "Exit" );
putValue( AbstractAction.SHORT_DESCRIPTION, "Exits" );
putValue( AbstractAction.MNEMONIC_KEY, new Integer( 'x' ) );
putValue( AbstractAction.SMALL_ICON, null );
}
public void actionPerformed( ActionEvent e )
{
// there should be a better way to do this but there is no close // and this seems to be what the system exit menu does, so ... MainFrame.this.dispatchEvent( new WindowEvent( MainFrame.this, WindowEvent.WINDOW_CLOSING ) ); } } // cExitAction } ==========================================
File 2:ComponentPrinter.java
/*
*
* To change the template for this generated file go to
* Window>Preferences>Java>Code Generation>
* Code and Comments
*/
package com.sas.test;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.print.PageFormat;
import java.awt.print.Pageable;
import java.awt.print.Printable;
import java.awt.print.PrinterException;
import javax.swing.JComponent;
import javax.swing.JTree;
import javax.swing.tree.DefaultTreeCellRenderer;
import javax.swing.tree.TreeCellRenderer;
/**
* WsComponentPrinter prints a component using the given page format. The
* component may be visible or not visible.
* <p>
* There are two ways to create a WsComponentPrinter. The first way is to just
* instantiate one (via new). The second way is to use one of the createPrinter
* methods. The difference is that there are extended versions of this class
* that do special things to make rendering a component to a printer better.
* For example, there is an extended version of the class for a JTree that sets
* its background colors to white so that the printed version looks like a
* document. Using the createPrinter methods will return these specialized
* versions of the component.
*/
public class ComponentPrinter implements Pageable, Printable
{
private JComponent m_cmp;
private PageFormat m_page;
private int m_nPagesX;
private int m_nPagesY;
private int m_xOrigin;
private int m_yOrigin;
/**
* Creates a component printer. Use this method to get a component-specific
* instance of this class. It is not required to use createPrinter but using
* it does ensure that a component specific version of WsComponentPrinter, if
* there is one, will be returned.
*
* @param cmp the component to print
* @param page the page format
*/
public static ComponentPrinter createPrinter( JComponent cmp, PageFormat page ) { return createPrinter( cmp, page, true ); }
/**
* Creates a component printer. Use this method to get a component-specific
* instance of this class. It is not required to use createPrinter but using
* it does ensure that a component specific version of WsComponentPrinter, if
* there is one, will be returned. This method also allows the caller to
* specify whether to print the component as is or with modifications to make
* it print nicer.
*
* @param cmp the component to print
* @param page the page format
* @param bAsIs true=print component as is,
* false=change foreground/background colors to black/white
*/
public static ComponentPrinter createPrinter( JComponent cmp, PageFormat page, boolean bAsIs ) { if (cmp instanceof JTree) return new cTreePrinter( (JTree) cmp, page, bAsIs ); else return new ComponentPrinter( cmp, page ); }
/**
* Constructs a component printer.
*
* @param cmp the component to print
* @param page the page format
*
* @see createPrinter(JComponent, PageFormat)
* @see createPrinter(JComponent, PageFormat, boolean)
*/
public ComponentPrinter( JComponent cmp, PageFormat page )
{
m_cmp = cmp;
m_page = page;
}
/**
* Disposes of the component printer. Resets the renderer if necessary. */ public void dispose() { }
//------------------------------------------------------------------------
// Pageable interface
//------------------------------------------------------------------------
/**
* Gets the number of pages it will take to print the tree.
*
* @return the number of pages
*
* @see java.awt.print.Pageable#getNumberOfPages()
*/
public int getNumberOfPages()
{
// get the height and width of the component
// if the component has not been sized, use its preferred size int cxCmp = m_cmp.getWidth(); int cyCmp = m_cmp.getHeight(); if ((cxCmp == 0) && (cyCmp == 0)) { m_cmp.setSize( m_cmp.getPreferredSize() ); cxCmp = m_cmp.getWidth(); cyCmp = m_cmp.getHeight(); } int cxPage = (int) m_page.getImageableWidth(); int cyPage = (int) m_page.getImageableHeight(); m_nPagesX = (cxCmp + cxPage - 1) / cxPage; m_nPagesY = (cyCmp + cyPage - 1) / cyPage; return m_nPagesX * m_nPagesY; }
/**
* Gets the page format for the page specified.
*
* @param iPage the page index
*
* @return the page format
*
* @throws IndexOutOfBoundsException if the page index is out of bounds.
*
* @see java.awt.print.Pageable#getPageFormat(int)
*/
public PageFormat getPageFormat( int iPage ) throws IndexOutOfBoundsException { validatePageIndex( iPage ); return m_page; }
/**
* Returns the printable responsible for rendering the page.
*
* @param iPage the page index
*
* @return the printable responsible for rendering the page
*
* @throws IndexOutOfBoundsException if the page index is out of bounds.
*
* @see java.awt.print.Pageable#getPrintable(int)
*/
public Printable getPrintable( int iPage ) throws IndexOutOfBoundsException { validatePageIndex( iPage ); m_xOrigin = (int) ((iPage % m_nPagesX) * m_page.getImageableWidth()); m_yOrigin = (int) ((iPage / m_nPagesX) * m_page.getImageableHeight()); return this; }
/**
* Validates the page index.
*
* @param iPage the page index
*
* @throws IndexOutOfBoundsException if the page index is out of bounds. */ protected void validatePageIndex( int iPage ) throws IndexOutOfBoundsException { if ((iPage < 0) || (iPage >= getNumberOfPages())) throw new IndexOutOfBoundsException(); }
//------------------------------------------------------------------------
// Printable interface
//------------------------------------------------------------------------
/**
* Prints the component.
*
* @param g the graphics context to which to render the page formatting
* @param page the page format
* @param iPage the page index
*
* @return PAGE_EXISTS if the page is rendered successfully or
* NO_SUCH_PAGE if the page does not exist (which is never returned)
*
* @throws PrinterException
*
* @see java.awt.print.Printable#print(Graphics, PageFormat, int) */ public int print( Graphics g, PageFormat page, int iPage ) throws PrinterException { // if the page format supports printing, then let it print if (page instanceof Printable)
((Printable) page).print( g, page, iPage );
System.out.println( "Printing:Orientation=" + page.getOrientation() ); // create a graphics context for drawing the formatted page so that // no changes are made to original graphic context. make sure the created // graphics context gets disposed Graphics2D g2d = (Graphics2D) g.create(); try { int xPage = (int) page.getImageableX(); int yPage = (int) page.getImageableY();
// int cxPage = (int) page.getImageableWidth(); -- for debug purposes below
// int cyPage = (int) page.getImageableHeight(); -- for debug purposes below
g2d.translate( xPage, yPage );
// draw the box and x for debugging purpose
// g2d.drawRect( 0, 0, cxPage, cyPage );
// g2d.drawLine( 0, 0, cxPage, cyPage );
// g2d.drawLine( cxPage, 0, 0, cyPage );
g2d.translate( -m_xOrigin, -m_yOrigin );
m_cmp.printAll( g2d );
}
finally
{
g2d.dispose();
}
return Printable.PAGE_EXISTS;
}
/**
* cTreePrinter prints a tree component. If the tree uses a
* DefaultTreeCellRenderer and the print is not "as is", the printer changes
* the colors of the tree to be black on white to give a better appearance
* when printing.
*/
protected static class cTreePrinter extends ComponentPrinter
{
private JTree m_tree;
private boolean m_bReset;
private Color m_clrBackground;
private Color m_clrBackgroundSelection;
private Color m_clrBackgroundNonSelection;
private Color m_clrTextSelection;
private Color m_clrTextNonSelection;
private Color m_clrBorderSelection;
/**
* Constructs a tree printer.
*
* @param tree the tree
* @param page the page format
* @param bAsIs true=print component as is,
* false=change foreground/background colors to black/white
*/
public cTreePrinter( JTree tree, PageFormat page, boolean bAsIs ) { super( tree, page ); m_tree = tree; if (!bAsIs) { TreeCellRenderer rdr = tree.getCellRenderer(); if (rdr instanceof DefaultTreeCellRenderer) { DefaultTreeCellRenderer rdrDefault = (DefaultTreeCellRenderer) rdr;
m_clrBackground = tree.getBackground();
m_clrBackgroundSelection = rdrDefault.getBackgroundSelectionColor();
m_clrBackgroundNonSelection = rdrDefault.getBackgroundNonSelectionColor();
m_clrTextSelection = rdrDefault.getTextSelectionColor();
m_clrTextNonSelection = rdrDefault.getTextNonSelectionColor();
m_clrBorderSelection = rdrDefault.getBorderSelectionColor();
m_bReset = true;
tree.setBackground( Color.white );
rdrDefault.setBackgroundSelectionColor( Color.white );
rdrDefault.setBackgroundNonSelectionColor( Color.white );
rdrDefault.setTextSelectionColor( Color.black );
rdrDefault.setTextNonSelectionColor( Color.black );
rdrDefault.setBorderSelectionColor( Color.white );
}
}
}
/**
* Disposes of a tree printer. Resets the renderer if necessary. */ public void dispose()