-
Bug
-
Resolution: Incomplete
-
P4
-
8u73, 9
-
x86
-
other
FULL PRODUCT VERSION :
build 1.8.0_73-b02
ADDITIONAL OS VERSION INFORMATION :
Windows 10
A DESCRIPTION OF THE PROBLEM :
When printing a JTable content, with icons, they are not reproduced in the same way as their appearence on screen.
On screen: OK
On printer: not OK
In a XPS file: not OK
In a PDF file OK
When printing On MAC, it is always OK. That's why I think it's a bug.
(Sorry for my english)
REPRODUCIBILITY :
This bug can be reproduced always.
---------- BEGIN SOURCE ----------
HERE IS A PART OF THE CLASS CONTAINING THE PRINTING PROCESS:
public class C_Pointage extends JPanel implements ActionListener, KeyListener
{
/.../
private final ImageIcon icnAttentionO, icnAttentionR;
/.../
// Constructeur:
public C_Pointage( C_GestionDonnees pGestionDonnees ) {
super();
/.../
private final C_DataPointage cDataPointage; // Classe de gestion des données de tblPointageImprimable;
private final C_JTableImprimable tblPointageImprimable; // JTable augmentée, pour gérer l'impression
/.../
// Chargement des ressources graphiques:
icnAttentionO = new ImageIcon( getClass().getResource( "/ICN_AttentionO.png" ));
icnAttentionR = new ImageIcon( getClass().getResource( "/ICN_AttentionR.png" ));
/.../
// CREATION DU TABLEAU DE POINTAGE AU CENTRE:
cDataPointage = new C_DataPointage();
tblPointageImprimable = new C_JTableImprimable( cDataPointage );
tblPointageImprimable.addKeyListener( this );
tblPointageImprimable.addMouseListener( cClicListe );
/.../
this.add( new JScrollPane( tblPointageImprimable, ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS, ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER ));
// Réglages des colonnes de C_JTableImprimable
TableColumn colonneTable = tblPointageImprimable.getColumnModel().getColumn( 0 ); // N° de ligne
/.../
colonneTable = tblPointageImprimable.getColumnModel().getColumn( 4 ); // A payer
colonneTable.setMinWidth( 37 );
colonneTable.setMaxWidth( 37 );
colonneTable.setCellRenderer( new CRenduIcones( SwingConstants.RIGHT ));
colonneTable.setHeaderRenderer( cRenduEntete );
/.../
}
/.../
}
=========================================================
HERE IS THE CellRenderer FOR THE ICONS IN THE 4th COLUMN. I HAVE SIMPLIFIED THE CODE AS FAR AS POSSIBLE. DOESN4T WORK ANYMAY:
private class CRenduIcones extends DefaultTableCellRenderer
{
private static final long serialVersionUID = 1L;
public CRenduIcones ( int alignement ) {
super();
setHorizontalAlignment( alignement );
setVerticalAlignment( SwingConstants.TOP );
}
@Override
public Component getTableCellRendererComponent( JTable jTbl, Object oVal, boolean yaselection, boolean yafocus, int l, int c ) {
super.getTableCellRendererComponent( jTbl, oVal, yaselection, yafocus, l, c );
setText( "" );
if(( l & 1 ) == 1 )
setIcon( icnAttentionR );
else
setIcon( icnAttentionO );
return this;
}
}
========================================================
HERE IS THE CLASS THAT MANAGE THE JTable'S DATA, A CLASSICAL MODEL:
private class C_DataPointage extends AbstractTableModel
{
private static final long serialVersionUID = 1L;
public C_DataPointage{
/.../
}
@Override
public Class<?> getColumnClass( int colonne ) { /.../ }
@Override
public int getRowCount() { /.../ }
@Override
public Object getValueAt( int ligne, int colonne ) { /.../ }
@Override
public boolean isCellEditable( int ligne, int colonne ) { /.../ }
}
======================================================
HERE IS THE CLASS FOR THE JOB PRINTING:
public static class C_JTableImprimable extends JTable
{
private static final long serialVersionUID = 1L;
private String sLigne1, sLigne2, sLigne3; // Lignes éventuelles dans l'en-tête
private boolean signature; // Indique s'il faut imprimer le cadre de signature
//CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC
public C_JTableImprimable( AbstractTableModel jTableTransmise ) {
super( jTableTransmise );
this.setDoubleBuffered( false ); // Pour l'impression
}
//CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC
/**
* Surcharge pour obtenir une impression personnalisée. L'en-tête et le pied de page sont ignorés pour être remplacé localement.
*
* @return Objet d'impression personnalisée
*/
@Override
public Printable getPrintable( PrintMode prtModeTransmis, MessageFormat enTeteTransmis, MessageFormat piedPageTransmis ) {
Printable prtDelegue = super.getPrintable( prtModeTransmis, enTeteTransmis, piedPageTransmis );
return new C_ImpressionDecoree( prtDelegue );
}
//----------------------------------------------------------------------------------------------------------------------------------------------------------------
private class C_ImpressionDecoree implements Printable
{
private PageFormat fmtZoneTablo;
private final Printable prtDelegataire;
final int l_logo_site, h_logo_site, l_logo_gemo, h_logo_gemo;
//CcccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccC
public C_ImpressionDecoree( Printable prtDelegueTransmis ) {
prtDelegataire = prtDelegueTransmis;
l_logo_site = imgLogoSite.getWidth() * 72 / 600; // Adaptation 600DPI...
h_logo_site = imgLogoSite.getHeight() * 72 / 600; // ... en contexte 72DPI
l_logo_gemo = imgGemoConcept.getWidth() * 72 / 600;
h_logo_gemo = imgGemoConcept.getHeight() * 72 / 600;
fmtZoneTablo = new PageFormat();
}
//CcccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccC
@Override
public int print( Graphics gContexte, PageFormat fmtPage, int index_page ) throws PrinterException {
Graphics2D g2D;
Paper infoPage;
int val_retour;
int x_pos, y_pos, h_texte;
// Détermination de la zone destinée à la table, compte tenu des logos situés en haut de page:
infoPage = new Paper();
if( fmtPage.getOrientation() == PageFormat.PORTRAIT )
{
infoPage.setSize( fmtPage.getWidth(), fmtPage.getHeight());
infoPage.setImageableArea( fmtPage.getImageableX(), fmtPage.getImageableY() + h_logo_site, fmtPage.getImageableWidth(), fmtPage.getImageableHeight() - h_logo_site );
}
else // Inversion des coordonnées
{
infoPage.setSize( fmtPage.getHeight(), fmtPage.getWidth());
infoPage.setImageableArea( fmtPage.getImageableY() + h_logo_site, fmtPage.getImageableX(), fmtPage.getImageableHeight() - h_logo_site, fmtPage.getImageableWidth());
}
fmtZoneTablo.setPaper( infoPage );
fmtZoneTablo.setOrientation( fmtPage.getOrientation());
g2D = (Graphics2D)gContexte.create();
val_retour = prtDelegataire.print( gContexte, fmtZoneTablo, index_page );
if( val_retour == NO_SUCH_PAGE )
{
g2D.dispose();
return val_retour; // Plus rien à imprimer
}
// Arrivé ici signifie que la table est imprimée, on rajoute la décoration:
g2D.setRenderingHint( RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON );
g2D.setRenderingHint( RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON );
g2D.setRenderingHint( RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY );
g2D.setRenderingHint( RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BICUBIC );
// Logo du club, en haut à gauche:
x_pos = 1 + (int)fmtPage.getImageableX(); // Tient compte de l'orientation
y_pos = 1 + (int)fmtPage.getImageableY();
g2D.drawImage( imgLogoSite, x_pos, y_pos, l_logo_site, h_logo_site, null );
// Lignes éventuelles dans l'en-tête
g2D.setFont( policeNormale );
h_texte = (int)g2D.getFontMetrics().getStringBounds( "H", g2D ).getHeight(); // Pour connaître la hauteur d'une ligne
if( sLigne1 != null )
g2D.drawString( sLigne1, x_pos + l_logo_site + 10, y_pos + h_texte );
if( sLigne2 != null )
g2D.drawString( sLigne2, x_pos + l_logo_site + 10, y_pos + h_texte + h_texte + 1 );
if( sLigne3 != null )
g2D.drawString( sLigne3, x_pos + l_logo_site + 10, y_pos + h_texte + h_texte + h_texte + 2 );
// Logo GémoConcept, en haut à droite:
x_pos = 1 + (int)( fmtPage.getImageableX() + fmtPage.getImageableWidth() - l_logo_gemo );
y_pos = 1 + (int)( fmtPage.getImageableY());
g2D.drawImage( imgGemoConcept, x_pos, y_pos, l_logo_gemo, h_logo_gemo, null );
// Rectangle de signature
if( signature )
{
g2D.drawRect( x_pos - 160, y_pos, 150, h_logo_site );
g2D.setFont( policeLabel );
h_texte = (int)g2D.getFontMetrics().getStringBounds( "H", g2D ).getHeight(); // Pour connaître la hauteur d'une ligne
g2D.drawString( "Signature:", x_pos - 155, y_pos + h_texte + 1 );
}
g2D.dispose();
return PAGE_EXISTS;
}
}
}
---------- END SOURCE ----------
CUSTOMER SUBMITTED WORKAROUND :
Nothing
build 1.8.0_73-b02
ADDITIONAL OS VERSION INFORMATION :
Windows 10
A DESCRIPTION OF THE PROBLEM :
When printing a JTable content, with icons, they are not reproduced in the same way as their appearence on screen.
On screen: OK
On printer: not OK
In a XPS file: not OK
In a PDF file OK
When printing On MAC, it is always OK. That's why I think it's a bug.
(Sorry for my english)
REPRODUCIBILITY :
This bug can be reproduced always.
---------- BEGIN SOURCE ----------
HERE IS A PART OF THE CLASS CONTAINING THE PRINTING PROCESS:
public class C_Pointage extends JPanel implements ActionListener, KeyListener
{
/.../
private final ImageIcon icnAttentionO, icnAttentionR;
/.../
// Constructeur:
public C_Pointage( C_GestionDonnees pGestionDonnees ) {
super();
/.../
private final C_DataPointage cDataPointage; // Classe de gestion des données de tblPointageImprimable;
private final C_JTableImprimable tblPointageImprimable; // JTable augmentée, pour gérer l'impression
/.../
// Chargement des ressources graphiques:
icnAttentionO = new ImageIcon( getClass().getResource( "/ICN_AttentionO.png" ));
icnAttentionR = new ImageIcon( getClass().getResource( "/ICN_AttentionR.png" ));
/.../
// CREATION DU TABLEAU DE POINTAGE AU CENTRE:
cDataPointage = new C_DataPointage();
tblPointageImprimable = new C_JTableImprimable( cDataPointage );
tblPointageImprimable.addKeyListener( this );
tblPointageImprimable.addMouseListener( cClicListe );
/.../
this.add( new JScrollPane( tblPointageImprimable, ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS, ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER ));
// Réglages des colonnes de C_JTableImprimable
TableColumn colonneTable = tblPointageImprimable.getColumnModel().getColumn( 0 ); // N° de ligne
/.../
colonneTable = tblPointageImprimable.getColumnModel().getColumn( 4 ); // A payer
colonneTable.setMinWidth( 37 );
colonneTable.setMaxWidth( 37 );
colonneTable.setCellRenderer( new CRenduIcones( SwingConstants.RIGHT ));
colonneTable.setHeaderRenderer( cRenduEntete );
/.../
}
/.../
}
=========================================================
HERE IS THE CellRenderer FOR THE ICONS IN THE 4th COLUMN. I HAVE SIMPLIFIED THE CODE AS FAR AS POSSIBLE. DOESN4T WORK ANYMAY:
private class CRenduIcones extends DefaultTableCellRenderer
{
private static final long serialVersionUID = 1L;
public CRenduIcones ( int alignement ) {
super();
setHorizontalAlignment( alignement );
setVerticalAlignment( SwingConstants.TOP );
}
@Override
public Component getTableCellRendererComponent( JTable jTbl, Object oVal, boolean yaselection, boolean yafocus, int l, int c ) {
super.getTableCellRendererComponent( jTbl, oVal, yaselection, yafocus, l, c );
setText( "" );
if(( l & 1 ) == 1 )
setIcon( icnAttentionR );
else
setIcon( icnAttentionO );
return this;
}
}
========================================================
HERE IS THE CLASS THAT MANAGE THE JTable'S DATA, A CLASSICAL MODEL:
private class C_DataPointage extends AbstractTableModel
{
private static final long serialVersionUID = 1L;
public C_DataPointage{
/.../
}
@Override
public Class<?> getColumnClass( int colonne ) { /.../ }
@Override
public int getRowCount() { /.../ }
@Override
public Object getValueAt( int ligne, int colonne ) { /.../ }
@Override
public boolean isCellEditable( int ligne, int colonne ) { /.../ }
}
======================================================
HERE IS THE CLASS FOR THE JOB PRINTING:
public static class C_JTableImprimable extends JTable
{
private static final long serialVersionUID = 1L;
private String sLigne1, sLigne2, sLigne3; // Lignes éventuelles dans l'en-tête
private boolean signature; // Indique s'il faut imprimer le cadre de signature
//CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC
public C_JTableImprimable( AbstractTableModel jTableTransmise ) {
super( jTableTransmise );
this.setDoubleBuffered( false ); // Pour l'impression
}
//CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC
/**
* Surcharge pour obtenir une impression personnalisée. L'en-tête et le pied de page sont ignorés pour être remplacé localement.
*
* @return Objet d'impression personnalisée
*/
@Override
public Printable getPrintable( PrintMode prtModeTransmis, MessageFormat enTeteTransmis, MessageFormat piedPageTransmis ) {
Printable prtDelegue = super.getPrintable( prtModeTransmis, enTeteTransmis, piedPageTransmis );
return new C_ImpressionDecoree( prtDelegue );
}
//----------------------------------------------------------------------------------------------------------------------------------------------------------------
private class C_ImpressionDecoree implements Printable
{
private PageFormat fmtZoneTablo;
private final Printable prtDelegataire;
final int l_logo_site, h_logo_site, l_logo_gemo, h_logo_gemo;
//CcccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccC
public C_ImpressionDecoree( Printable prtDelegueTransmis ) {
prtDelegataire = prtDelegueTransmis;
l_logo_site = imgLogoSite.getWidth() * 72 / 600; // Adaptation 600DPI...
h_logo_site = imgLogoSite.getHeight() * 72 / 600; // ... en contexte 72DPI
l_logo_gemo = imgGemoConcept.getWidth() * 72 / 600;
h_logo_gemo = imgGemoConcept.getHeight() * 72 / 600;
fmtZoneTablo = new PageFormat();
}
//CcccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccC
@Override
public int print( Graphics gContexte, PageFormat fmtPage, int index_page ) throws PrinterException {
Graphics2D g2D;
Paper infoPage;
int val_retour;
int x_pos, y_pos, h_texte;
// Détermination de la zone destinée à la table, compte tenu des logos situés en haut de page:
infoPage = new Paper();
if( fmtPage.getOrientation() == PageFormat.PORTRAIT )
{
infoPage.setSize( fmtPage.getWidth(), fmtPage.getHeight());
infoPage.setImageableArea( fmtPage.getImageableX(), fmtPage.getImageableY() + h_logo_site, fmtPage.getImageableWidth(), fmtPage.getImageableHeight() - h_logo_site );
}
else // Inversion des coordonnées
{
infoPage.setSize( fmtPage.getHeight(), fmtPage.getWidth());
infoPage.setImageableArea( fmtPage.getImageableY() + h_logo_site, fmtPage.getImageableX(), fmtPage.getImageableHeight() - h_logo_site, fmtPage.getImageableWidth());
}
fmtZoneTablo.setPaper( infoPage );
fmtZoneTablo.setOrientation( fmtPage.getOrientation());
g2D = (Graphics2D)gContexte.create();
val_retour = prtDelegataire.print( gContexte, fmtZoneTablo, index_page );
if( val_retour == NO_SUCH_PAGE )
{
g2D.dispose();
return val_retour; // Plus rien à imprimer
}
// Arrivé ici signifie que la table est imprimée, on rajoute la décoration:
g2D.setRenderingHint( RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON );
g2D.setRenderingHint( RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON );
g2D.setRenderingHint( RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY );
g2D.setRenderingHint( RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BICUBIC );
// Logo du club, en haut à gauche:
x_pos = 1 + (int)fmtPage.getImageableX(); // Tient compte de l'orientation
y_pos = 1 + (int)fmtPage.getImageableY();
g2D.drawImage( imgLogoSite, x_pos, y_pos, l_logo_site, h_logo_site, null );
// Lignes éventuelles dans l'en-tête
g2D.setFont( policeNormale );
h_texte = (int)g2D.getFontMetrics().getStringBounds( "H", g2D ).getHeight(); // Pour connaître la hauteur d'une ligne
if( sLigne1 != null )
g2D.drawString( sLigne1, x_pos + l_logo_site + 10, y_pos + h_texte );
if( sLigne2 != null )
g2D.drawString( sLigne2, x_pos + l_logo_site + 10, y_pos + h_texte + h_texte + 1 );
if( sLigne3 != null )
g2D.drawString( sLigne3, x_pos + l_logo_site + 10, y_pos + h_texte + h_texte + h_texte + 2 );
// Logo GémoConcept, en haut à droite:
x_pos = 1 + (int)( fmtPage.getImageableX() + fmtPage.getImageableWidth() - l_logo_gemo );
y_pos = 1 + (int)( fmtPage.getImageableY());
g2D.drawImage( imgGemoConcept, x_pos, y_pos, l_logo_gemo, h_logo_gemo, null );
// Rectangle de signature
if( signature )
{
g2D.drawRect( x_pos - 160, y_pos, 150, h_logo_site );
g2D.setFont( policeLabel );
h_texte = (int)g2D.getFontMetrics().getStringBounds( "H", g2D ).getHeight(); // Pour connaître la hauteur d'une ligne
g2D.drawString( "Signature:", x_pos - 155, y_pos + h_texte + 1 );
}
g2D.dispose();
return PAGE_EXISTS;
}
}
}
---------- END SOURCE ----------
CUSTOMER SUBMITTED WORKAROUND :
Nothing