Bonjour,
j'ai un problème d'impression avec en-tête. D'après mes recherches, j'ai puis créer l'impression avec le logo et une ligne centrée a partir de celle discussion http://https://www.developpez.net/forums/d1822000/java/interfaces-graphiques-java/awt-swing/ajouter-logo-l-entete-print-jtable/.
J'ai aussi eu les deux codes permettant d'avoir plusieurs lignes d'en l'entête mais sans logo.
Depuis trois jours je cherche à combiner les deux codes pour avoir une impression avec logo et plusieurs ligne dans l'en-tête. Mais je n'y parviens pas. Je sollicite votre aide pour le réaliser.
Voir ci les codes :
*****Pour l'affiche du logo et d'une seule ligne dans l'en-tête
1- Pour l'affichage en demo
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
package Test;
 
import java.awt.BorderLayout;
import java.awt.FlowLayout;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.geom.Rectangle2D;
import java.awt.image.BufferedImage;
import java.awt.print.PageFormat;
import java.awt.print.Printable;
import java.awt.print.PrinterException;
import java.awt.print.PrinterJob;
import java.io.IOException;
import java.net.URL;
import java.util.Arrays;
 
import javax.imageio.ImageIO;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.JTable.PrintMode;
import javax.swing.SwingConstants;
 
import Test.TablePrinter.HeadBandPrintable;
 
public class TablePrinterDemo {
 
 
	public static void main(String[] args) throws IOException {
 
		HeadBandPrintable header = new HeadBandPrintable() {
			//BufferedImage but=new BufferedImage(20, 25, BufferedImage.TYPE_INT_ARGB);
			URL urlImage = getClass().getResource("/Ireport/Logo.PNG");
			BufferedImage image = ImageIO.read(urlImage);
			@Override
			public int print(Graphics graphics, PageFormat pageFormat, int pageIndex) throws PrinterException { 
				graphics.drawImage(image,10,10,100, 120, null); 
	               graphics.setFont(Font.decode("Arial-NORMAL-12")); 
				TextUtils.drawString(graphics, "Mon impression avec logo", new Rectangle2D.Double(pageFormat.getImageableX(),pageFormat.getImageableY(),pageFormat.getImageableWidth(),pageFormat.getImageableHeight()), SwingConstants.CENTER, SwingConstants.CENTER);
				return Printable.NO_SUCH_PAGE;
			}
 
			@Override
			public double getHeight() {
				return 150;
			}
 
		};
 
		HeadBandPrintable footer = new HeadBandPrintable() {
 
			@Override
			public int print(Graphics graphics, PageFormat pageFormat, int pageIndex) throws PrinterException {
	               graphics.setFont(Font.decode("Arial-NORMAL-12")); 
				TextUtils.drawString(graphics, "Page " + (pageIndex+1), new Rectangle2D.Double(pageFormat.getImageableX(),pageFormat.getImageableY(),pageFormat.getImageableWidth(),pageFormat.getImageableHeight()), pageIndex%2==0?SwingConstants.RIGHT:SwingConstants.RIGHT, SwingConstants.CENTER);
				return Printable.NO_SUCH_PAGE;
			}
 
			@Override
			public double getHeight() {
				return 20;
			}
 
		};
 
 
		JFrame frame = new JFrame("Démo");
		frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		String[] columns = {"1","2","3"};
		Object[][] data = new Object[100][columns.length];
		for(Object[] row : data) {
			Arrays.fill(row, "xxx");
		}
 
		JTable table = new JTable(data, columns);
		JPanel panel = new JPanel(new BorderLayout());
		panel.add(table);
		panel.add(table.getTableHeader(),BorderLayout.NORTH);
		frame.add(new JScrollPane(panel));
 
		JPanel buttonPanel = new JPanel(new FlowLayout(FlowLayout.TRAILING,5,5));
		JButton printButton = new JButton("Imprimer");
		printButton.addActionListener(e->printTable(table, header, footer));
		buttonPanel.add(printButton);
		frame.add(buttonPanel,BorderLayout.SOUTH);
 
		frame.setSize(300, 300);
		frame.setLocationRelativeTo(null);
		frame.setVisible(true);
 
 
	}
 
	private static void printTable(JTable table, HeadBandPrintable header, HeadBandPrintable footer) {
 
		PrinterJob job = PrinterJob.getPrinterJob();
		job.setPrintable(new TablePrinter(table, PrintMode.FIT_WIDTH, header, footer));
		boolean doPrint = job.printDialog();
		if (doPrint) {
		    try {
		        job.print();
		    } catch (PrinterException e) {
		    	e.printStackTrace();
		        JOptionPane.showMessageDialog(table, "Erreur d'impression");
		    }
		}
	}
 
 
}
2- Pour le model d'impression personnalisé (pour une seule ligne dans l'en-tête)
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
package Test;
 
import java.awt.Graphics;
import java.awt.Insets;
import java.awt.geom.Rectangle2D;
import java.awt.print.PageFormat;
import java.awt.print.Paper;
import java.awt.print.Printable;
import java.awt.print.PrinterException;
 
import javax.swing.JTable;
import javax.swing.JTable.PrintMode;
 
public class TablePrinter implements Printable {
 
	private JTable table;
	private HeadBandPrintable header;
	private HeadBandPrintable footer;
	private Printable tablePrintable;
	private PrintMode printMode;
	private int lastPage;
	private Insets tableInsets;
 
	public TablePrinter(JTable table, PrintMode printMode, HeadBandPrintable header, HeadBandPrintable footer) {
		this(table, printMode, header, footer, null);
	}
 
	public TablePrinter(JTable table, PrintMode printMode, HeadBandPrintable header, HeadBandPrintable footer, int marginh, int marginv) {
		this(table, printMode, header, footer, new Insets(marginv, marginh, marginv, marginh));
	}
 
	public TablePrinter(JTable table, PrintMode printMode, HeadBandPrintable header, HeadBandPrintable footer, Insets tableInsets) {
		this.table=table;
		this.header=header;
		this.footer=footer;
		this.printMode=printMode;
		this.tableInsets=tableInsets==null?new Insets(0,0,0,0):tableInsets;
	}
 
	public void reset() {
		tablePrintable=null;
	}
 
	public int print(Graphics graphics, PageFormat pageFormat, int pageIndex) throws PrinterException {
 
		if ( tablePrintable==null || pageIndex<lastPage) {
			tablePrintable = this.table.getPrintable(printMode, null, null);
		}
 
		double headerHeight;
		if ( header!=null ) {
			headerHeight = Math.max(0, header.getHeight());
		}
		else {
			headerHeight = 0;
		}
 
		double footerHeight;
		if ( footer!=null ) {
			footerHeight = Math.max(0, footer.getHeight());
		}
		else {
			footerHeight = 0;
		}
 
		PageFormat tablePageFormat;
		if ( headerHeight!=0 || footerHeight!=0 || tableInsets.top!=0 || tableInsets.bottom!=0 || tableInsets.left!=0 || tableInsets.right!=0 ) {
 
			tablePageFormat = new HeaderFooterPageFormat(pageFormat, headerHeight, footerHeight, tableInsets); 
 
		}
		else {
			tablePageFormat = pageFormat;
		}
 
		int page = tablePrintable.print(graphics, tablePageFormat, pageIndex);
		if (page==Printable.PAGE_EXISTS) {
			if ( header!=null ) {
				HeaderFooterPageFormat headerPageFormat = new HeaderFooterPageFormat(pageFormat, 0, tablePageFormat.getImageableHeight()+footerHeight+tableInsets.top+tableInsets.bottom,null); 
				header.print(graphics, headerPageFormat, pageIndex);
			}
			if ( footer!=null ) {
				HeaderFooterPageFormat footerPageFormat = new HeaderFooterPageFormat(pageFormat, tablePageFormat.getImageableHeight()+headerHeight+tableInsets.top+tableInsets.bottom, 0,null); 
				footer.print(graphics, footerPageFormat, pageIndex);
			}
		}
		return page;
 
	}
 
	private static class HeaderFooterPageFormat extends PageFormat {
 
		private PageFormat pageFormat;
		private double headerHeight;
		private double footerHeight;
		private Rectangle2D.Double imageable;
		private Insets insets;
		private boolean withInsets; 
 
		public HeaderFooterPageFormat(PageFormat pageFormat, double headerHeight, double footerHeight, Insets insets) throws PrinterException {
			this.pageFormat = pageFormat;
			this.headerHeight = headerHeight;
			this.footerHeight = footerHeight;
			this.insets = insets==null?new Insets(0,0,0,0):insets;
			this.withInsets = insets!=null;
			computeImageable();
 
		}
 
		private void computeImageable() throws PrinterException {
			double height = this.pageFormat.getImageableHeight()-headerHeight-footerHeight-insets.top-insets.bottom;
			double width = this.pageFormat.getImageableWidth()-insets.left-insets.right;
			if (height<0 || width<0 ) {
				throw new PrinterException("Not enough space to print - format: " + this.pageFormat.getImageableHeight() + " - header: " + headerHeight + " - footer: " + footerHeight + (withInsets?(" margins: " + insets):""));
			}
			imageable = new Rectangle2D.Double(pageFormat.getImageableX()+insets.left, 
					pageFormat.getImageableY()+headerHeight+insets.top, pageFormat.getImageableWidth()-insets.left-insets.right, height);
		} 
 
		@Override
		public double getHeight() {
			return pageFormat.getHeight();
		}
 
		@Override
		public double getWidth() { 
			return pageFormat.getWidth();
		}
 
		@Override
		public Paper getPaper() { 
			return pageFormat.getPaper();
		}
 
		@Override
		public int getOrientation() { 
			return pageFormat.getOrientation();
		}
 
		@Override
		public double[] getMatrix() { 
			return pageFormat.getMatrix();
		}
 
		@Override
		public double getImageableX() {
			return imageable.getX();
		}
 
		@Override
		public double getImageableWidth() { 
			return imageable.getWidth();
		}
 
		@Override
		public double getImageableY() {
			return imageable.getY();
		}
 
		@Override
		public double getImageableHeight() {
			return imageable.getHeight();
		}
 
		@Override
		public void setOrientation(int orientation) throws IllegalArgumentException {
			pageFormat.setOrientation(orientation);
			try {
				computeImageable();
			} catch (PrinterException e) {
				throw new RuntimeException(e);
			}
		}
 
		@Override
		public void setPaper(Paper paper) {
			pageFormat.setPaper(paper);
			try {
				computeImageable();
			} catch (PrinterException e) {
				throw new RuntimeException(e);
			}
		}
 
		public PageFormat getPageFormat() {
			return pageFormat;
		}
 
	} 
 
	public static interface HeadBandPrintable extends Printable {
 
		double getHeight();
 
		int print(Graphics graphics, PageFormat pageFormat, int pageIndex)
                throws PrinterException;
 
	}
 
}
3- Pour affiché le texte
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
package Test;
 
import java.awt.Dimension;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.Insets;
import java.awt.geom.Rectangle2D;
 
import javax.swing.SwingConstants;
 
public class TextUtils {
 
    /**
       * Obtient la taille de l'espace pris par le texte
       */  
public static Dimension getSize(Graphics g, String string) {
	return getSize(g, string, null);
}
 
    /**
       * Obtient la taille de l'espace pris par le texte avec des marges
       */  
public static Dimension getSize(Graphics g, String string, Insets insets) {
	return getSize(g, string, insets==null?new Insets(0,0,0,0):insets);
}
 
    /**
       * Obtient la taille de l'espace pris par le texte avec des marges
       */  
public static Dimension getSize(Graphics g, String string, int top, int left, int bottom, int right) {
 
	FontMetrics fontMetrics = g.getFontMetrics();
	Rectangle2D textBounds = fontMetrics.getStringBounds(string, g);
	return new Dimension((int)(textBounds.getWidth()+left+right), (int)(textBounds.getHeight()+top+bottom));
 
}
 
    /**
       * Ecrit un texte aligné sur un point
       * @param g
       * @param string
       * @param x du point
       * @param y du point
       * @param halign SwingConstants.LEFT, SwingConstants.RIGHT ou SwingConstants.CENTER
       * @param valign SwingConstants.TOP, SwingConstants.BOTTOM ou SwingConstants.CENTER
       */
public static void drawString(Graphics g, String string, int x, int y, int halign, int valign) {
	FontMetrics fontMetrics = g.getFontMetrics();
	Rectangle2D bounds = fontMetrics.getStringBounds(string, g);
 
	double xx=x;
	double yy=y;
 
	switch(halign) {
	case SwingConstants.CENTER:
		xx-=bounds.getWidth()/2;
		break;
	case SwingConstants.RIGHT:
		xx-=bounds.getWidth();
		break;
	}
	switch(valign) {
	case SwingConstants.CENTER:
		yy -= bounds.getHeight()/2;
		break;
	case SwingConstants.BOTTOM:
		yy -= bounds.getHeight() - fontMetrics.getDescent();
		break;
	case SwingConstants.TOP:
		yy -= bounds.getHeight() - fontMetrics.getAscent();
		break;
	} 
	bounds = new Rectangle2D.Double(xx, yy, bounds.getWidth(), bounds.getHeight());
	drawString(g, string, bounds, SwingConstants.CENTER, SwingConstants.CENTER); 
}
 
    /**
       * Ecrit un texte aligné sur un rectangle
       * @param g
       * @param string
       * @param bounds rectangle
       * @param halign SwingConstants.LEFT, SwingConstants.RIGHT ou SwingConstants.CENTER
       * @param valign SwingConstants.TOP, SwingConstants.BOTTOM ou SwingConstants.CENTER
       */
public static void drawString(Graphics g, String string, Rectangle2D bounds, int halign, int valign) {
 
	FontMetrics fontMetrics = g.getFontMetrics();
	Rectangle2D textBounds = fontMetrics.getStringBounds(string, g);
	double textWidth = textBounds.getWidth();
 
	double x,y;
 
	switch (halign) {
	case SwingConstants.LEFT:
		x = bounds.getX(); 
		break;
	case SwingConstants.RIGHT:
		x = bounds.getX() + bounds.getWidth() - textWidth;
		break;
	case SwingConstants.CENTER:
	default:
		x = bounds.getX()
		+ (bounds.getWidth() - textWidth) / 2;
		break;
	}
	switch (valign) {
	case SwingConstants.TOP:
		y = bounds.getY() + fontMetrics.getAscent() - fontMetrics.getDescent();
		break;
	case SwingConstants.BOTTOM:
		y = bounds.getY()
		+ bounds.getHeight()  - fontMetrics.getDescent() ;
		break;
	case SwingConstants.CENTER:
	default:
		y = bounds.getY()
		+ bounds.getHeight()/ 2  - ( ( fontMetrics.getAscent() + fontMetrics.getDescent() ) / 2 ) + fontMetrics.getAscent()  ;
		break;
	}	 
 
 
	g.drawString(string, (int)x, (int)y);
 
}
 
}
*********Pour l'affichage de plusieurs lignes dans l'en-tête sans logo
1- Pour le bouton d'impression
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
	 try {
				        PrinterJob job = PrinterJob.getPrinterJob();
 
				        MessageFormat[] header = new MessageFormat[3];
 
				        header[0] = new MessageFormat("line 1");
				        header[1] = new MessageFormat("DEPARTEMENT DE VENTE");
				        header[2] = new MessageFormat("LISTE DES CLIENT");
 
				        MessageFormat[] footer = new MessageFormat[2];
				        footer[0] = new MessageFormat("");
				        footer[1] = new MessageFormat("-{1}-");
				        job.setPrintable(new MyTablePrintable(table, JTable.PrintMode.FIT_WIDTH, header, footer));
				        job.printDialog();
				        job.print();
 
				    } catch (Exception ex) {
				    }
2- pour le modèle personnalisé de plusieurs lignes
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
package PresentationRapport;
 
import javax.swing.table.*;
import java.awt.*;
import java.awt.print.*;
import java.awt.geom.*;
import java.text.MessageFormat;
import javax.swing.JTable;
 
/**
 * An implementation of <code>Printable</code> for printing
 * <code>JTable</code>s.
 * <p>
 * This implementation spreads table rows naturally in sequence across multiple
 * pages, fitting as many rows as possible per page. The distribution of
 * columns, on the other hand, is controlled by a printing mode parameter passed
 * to the constructor. When <code>JTable.PrintMode.NORMAL</code> is used, the
 * implementation handles columns in a similar manner to how it handles rows,
 * spreading them across multiple pages (in an order consistent with the table's
 * <code>ComponentOrientation</code>). When
 * <code>JTable.PrintMode.FIT_WIDTH</code> is given, the implementation scales
 * the output smaller if necessary, to ensure that all columns fit on the page.
 * (Note that width and height are scaled equally, ensuring that the aspect
 * ratio remains the same).
 * <p>
 * The portion of table printed on each page is headed by the appropriate
 * section of the table's <code>JTableHeader</code>.
 * <p>
 * Header and footer text can be added to the output by providing
 * <code>MessageFormat</code> instances to the constructor. The printing code
 * requests Strings from the formats by calling their <code>format</code> method
 * with a single parameter: an <code>Object</code> array containing a single
 * element of type <code>Integer</code>, representing the current page number.
 * <p>
 * There are certain circumstances where this <code>Printable</code> cannot fit
 * items appropriately, resulting in clipped output. These are:
 * <ul>
 * <li>In any mode, when the header or footer text is too wide to fit completely
 * in the printable area. The implementation prints as much of the text as
 * possible starting from the beginning, as determined by the table's
 * <code>ComponentOrientation</code>.
 * <li>In any mode, when a row is too tall to fit in the printable area. The
 * upper most portion of the row is printed and no lower border is shown.
 * <li>In <code>JTable.PrintMode.NORMAL</code> when a column is too wide to fit
 * in the printable area. The center of the column is printed and no left and
 * right borders are shown.
 * </ul>
 * <p>
 * It is entirely valid for a developer to wrap this <code>Printable</code>
 * inside another in order to create complex reports and documents. They may
 * even request that different pages be rendered into different sized printable
 * areas. The implementation was designed to handle this by performing most of
 * its calculations on the fly. However, providing different sizes works best
 * when <code>JTable.PrintMode.FIT_WIDTH</code> is used, or when only the
 * printable width is changed between pages. This is because when it is printing
 * a set of rows in <code>JTable.PrintMode.NORMAL</code> and the implementation
 * determines a need to distribute columns across pages, it assumes that all of
 * those rows will fit on each subsequent page needed to fit the columns.
 * <p>
 * It is the responsibility of the developer to ensure that the table is not
 * modified in any way after this <code>Printable</code> is created (invalid
 * modifications include changes in: size, renderers, or underlying data). The
 * behavior of this <code>Printable</code> is undefined if the table is changed
 * at any time after creation.
 *
 * @author Shannon Hickey
 * @version 1.41 11/17/05
 */
class MyTablePrintable implements Printable {
 
    /**
     * The table to print.
     */
    private static JTable table;
 
    /**
     * For quick reference to the table's header.
     */
    private JTableHeader header;
 
    /**
     * For quick reference to the table's column model.
     */
    private TableColumnModel colModel;
 
    /**
     * To save multiple calculations of total column width.
     */
    private int totalColWidth;
 
    /**
     * The printing mode of this printable.
     */
    private JTable.PrintMode printMode;
 
    /**
     * Provides the header text for the table.
     */
    private MessageFormat[] headerFormat;
 
    /**
     * Provides the footer text for the table.
     */
    private MessageFormat[] footerFormat;
 
    /**
     * The most recent page index asked to print.
     */
    private int last = -1;
 
    /**
     * The next row to print.
     */
    private int row = 0;
 
    /**
     * The next column to print.
     */
    private int col = 0;
 
    /**
     * Used to store an area of the table to be printed.
     */
    private final Rectangle clip = new Rectangle(0, 0, 0, 0);
 
    /**
     * Used to store an area of the table's header to be printed.
     */
    private final Rectangle hclip = new Rectangle(0, 0, 0, 0);
 
    /**
     * Saves the creation of multiple rectangles.
     */
    private final Rectangle tempRect = new Rectangle(0, 0, 0, 0);
 
    /**
     * Vertical space to leave between table and header/footer text.
     */
    private static final int H_F_SPACE = 8;
 
    /**
     * Font size for the header text.
     */
    private static final float HEADER_FONT_SIZE = 15.0f;
 
    /**
     * Font size for the footer text.
     */
    private static final float FOOTER_FONT_SIZE = 10.0f;
 
    /**
     * The font to use in rendering header text.
     */
    private Font headerFont;
 
    /**
     * The font to use in rendering footer text.
     */
    private Font footerFont;
 
    /**
     * Create a new <code>TablePrintable</code> for the given
     * <code>JTable</code>. Header and footer text can be specified using the
     * two <code>MessageFormat</code> parameters. When called upon to provide a
     * String, each format is given the current page number.
     *
     * @param table the table to print
     * @param printMode the printing mode for this printable
     * @param headerFormat a <code>MessageFormat</code> specifying the text to
     * be used in printing a header, or null for none
     * @param footerFormat a <code>MessageFormat</code> specifying the text to
     * be used in printing a footer, or null for none
     * @throws IllegalArgumentException if passed an invalid print mode
     */
    public MyTablePrintable(JTable table,
            JTable.PrintMode printMode,
            MessageFormat[] headerFormat,
            MessageFormat[] footerFormat) {
 
        this.table = table;
 
        header = table.getTableHeader();
        colModel = table.getColumnModel();
        totalColWidth = colModel.getTotalColumnWidth();
 
        if (header != null) {
            // the header clip height can be set once since it's unchanging
            hclip.height = header.getHeight();
        }
 
        this.printMode = printMode;
 
        this.headerFormat = headerFormat;
        this.footerFormat = footerFormat;
 
        // derive the header and footer font from the table's font
        headerFont = table.getFont().deriveFont(Font.BOLD,
                HEADER_FONT_SIZE);
        footerFont = table.getFont().deriveFont(Font.PLAIN,
                FOOTER_FONT_SIZE);
    }
 
    /**
     * Prints the specified page of the table into the given {@link Graphics}
     * context, in the specified format.
     *
     * @param graphics the context into which the page is drawn
     * @param pageFormat the size and orientation of the page being drawn
     * @param pageIndex the zero based index of the page to be drawn
     * @return PAGE_EXISTS if the page is rendered successfully, or NO_SUCH_PAGE
     * if a non-existent page index is specified
     * @throws PrinterException if an error causes printing to be aborted
     */
    public int print(Graphics graphics, PageFormat pageFormat, int pageIndex)
            throws PrinterException {
 
        // for easy access to these values
        final int imgWidth = (int) pageFormat.getImageableWidth();
        final int imgHeight = (int) pageFormat.getImageableHeight();
 
        if (imgWidth <= 0) {
            throw new PrinterException("Width of printable area is too small.");
        }
 
        // to pass the page number when formatting the header and footer text
        Object[] pageNumber = new Object[]{new Integer(pageIndex + 1)};
 
        // fetch the formatted header text, if any
        String[] headerText = null;
        if (headerFormat != null) {
            headerText = new String[headerFormat.length];
            for (int i = 0; i < headerFormat.length; i++) {
                headerText[i] = headerFormat[i].format(pageNumber);
            }
        }
 
        // fetch the formatted footer text, if any
        String[] footerText = null;
        if (footerFormat != null) {
            footerText = new String[footerFormat.length];
            for (int i = 0; i < footerFormat.length; i++) {
                footerText[i] = footerFormat[i].format(pageNumber);
            }
        }
 
        // to store the bounds of the header and footer text
        Rectangle2D[] hRect = null;
        Rectangle2D[] fRect = null;
 
        // the amount of vertical space needed for the header and footer text
        int headerTextSpace = 15;
        int footerTextSpace = 0;
 
        // the amount of vertical space available for printing the table
        int availableSpace = imgHeight;
 
        // if there's header text, find out how much space is needed for it
        // and subtract that from the available space
        if (headerText != null) {
            graphics.setFont(headerFont);
            hRect = new Rectangle2D[headerText.length];
            for (int i = 0; i < headerText.length; i++) {
                hRect[i] = graphics.getFontMetrics().getStringBounds(headerText[i], graphics);
                headerTextSpace += (int) Math.ceil(hRect[i].getHeight());
            }
            availableSpace -= headerTextSpace + H_F_SPACE;
        }
 
        // if there's footer text, find out how much space is needed for it
        // and subtract that from the available space
        if (footerText != null) {
            graphics.setFont(footerFont);
            fRect = new Rectangle2D[footerText.length];
            for (int i = 0; i < footerText.length; i++) {
                fRect[i] = graphics.getFontMetrics().getStringBounds(footerText[i], graphics);
                footerTextSpace += (int) Math.ceil(fRect[i].getHeight());
            }
            availableSpace -= footerTextSpace + H_F_SPACE;
        }
 
        if (availableSpace <= 0) {
            throw new PrinterException("Height of printable area is too small.");
        }
 
        // depending on the print mode, we may need a scale factor to
        // fit the table's entire width on the page
        double sf = 1.0D;
        if (printMode == JTable.PrintMode.FIT_WIDTH
                && totalColWidth > imgWidth) {
 
            // if not, we would have thrown an acception previously
            assert imgWidth > 0;
 
            // it must be, according to the if-condition, since imgWidth > 0
            assert totalColWidth > 1;
 
            sf = (double) imgWidth / (double) totalColWidth;
        }
 
        // dictated by the previous two assertions
        assert sf > 0;
 
        // This is in a loop for two reasons:
        // First, it allows us to catch up in case we're called starting
        // with a non-zero pageIndex. Second, we know that we can be called
        // for the same page multiple times. The condition of this while
        // loop acts as a check, ensuring that we don't attempt to do the
        // calculations again when we are called subsequent times for the
        // same page.
        while (last < pageIndex) {
            // if we are finished all columns in all rows
            if (row >= table.getRowCount() && col == 0) {
                return NO_SUCH_PAGE;
            }
 
            // rather than multiplying every row and column by the scale factor
            // in findNextClip, just pass a width and height that have already
            // been divided by it
            int scaledWidth = (int) (imgWidth / sf);
            int scaledHeight = (int) ((availableSpace - hclip.height) / sf);
 
            // calculate the area of the table to be printed for this page
            findNextClip(scaledWidth, scaledHeight);
 
            last++;
        }
 
        // translate into the co-ordinate system of the pageFormat
        Graphics2D g2d = (Graphics2D) graphics;
        g2d.translate(pageFormat.getImageableX(), pageFormat.getImageableY());
 
        // to save and store the transform
        AffineTransform oldTrans;
 
        // if there's footer text, print it at the bottom of the imageable area
        if (footerText != null) {
            oldTrans = g2d.getTransform();
 
            g2d.translate(0, imgHeight - footerTextSpace);
            for (int i = 0; i < footerText.length; i++) {
                printText(g2d, footerText[i], fRect[i], footerFont, i, imgWidth);
            }
 
            g2d.setTransform(oldTrans);
        }
 
        // if there's header text, print it at the top of the imageable area
        // and then translate downwards
        if (headerText != null) {
            for (int i = 0; i < headerText.length; i++) {
                printText(g2d, headerText[i], hRect[i], headerFont, i, imgWidth);
            }
 
            g2d.translate(0, headerTextSpace + H_F_SPACE);
        }
 
        // constrain the table output to the available space
        tempRect.x = 0;
        tempRect.y = 0;
        tempRect.width = imgWidth;
        tempRect.height = availableSpace;
        g2d.clip(tempRect);
 
        // if we have a scale factor, scale the graphics object to fit
        // the entire width
        if (sf != 1.0D) {
            g2d.scale(sf, sf);
 
            // otherwise, ensure that the current portion of the table is
            // centered horizontally
        } else {
            int diff = (imgWidth - clip.width) / 2;
            g2d.translate(diff, 0);
        }
 
        // store the old transform and clip for later restoration
        oldTrans = g2d.getTransform();
        Shape oldClip = g2d.getClip();
 
        // if there's a table header, print the current section and
        // then translate downwards
        if (header != null) {
            hclip.x = clip.x;
            hclip.width = clip.width;
 
            g2d.translate(-hclip.x, 0);
            g2d.clip(hclip);
            header.print(g2d);
 
            // restore the original transform and clip
            g2d.setTransform(oldTrans);
            g2d.setClip(oldClip);
 
            // translate downwards
            g2d.translate(0, hclip.height);
        }
 
        // print the current section of the table
        g2d.translate(-clip.x, -clip.y);
        g2d.clip(clip);
        table.print(g2d);
 
        // restore the original transform and clip
        g2d.setTransform(oldTrans);
        g2d.setClip(oldClip);
 
        // draw a box around the table
        g2d.setColor(Color.BLACK);
        g2d.drawRect(0, 0, clip.width, hclip.height + clip.height);
 
        return PAGE_EXISTS;
    }
 
    /**
     * A helper method that encapsulates common code for rendering the header
     * and footer text.
     *
     * @param g2d the graphics to draw into
     * @param text the text to draw, non null
     * @param rect the bounding rectangle for this text, as calculated at the
     * given font, non null
     * @param font the font to draw the text in, non null
     * @param imgWidth the width of the area to draw into
     */
    private void printText(Graphics2D g2d,
            String text,
            Rectangle2D rect,
            Font font,
            int textIndex,
            int imgWidth) {
 
        //int tx = -(int)(Math.ceil(rect.getWidth()) - imgWidth); // for right allign
        int tx = 0; // for left allign
 
        int ty = textIndex * (int) Math.ceil(Math.abs(rect.getY()));
        g2d.setColor(Color.BLACK);
        g2d.setFont(font);
        g2d.drawString(text, tx, ty);
    }
 
    /**
     * Calculate the area of the table to be printed for the next page. This
     * should only be called if there are rows and columns left to print.
     *
     * To avoid an infinite loop in printing, this will always put at least one
     * cell on each page.
     *
     * @param pw the width of the area to print in
     * @param ph the height of the area to print in
     */
    private void findNextClip(int pw, int ph) {
        final boolean ltr = table.getComponentOrientation().isLeftToRight();
 
        // if we're ready to start a new set of rows
        if (col == 0) {
            if (ltr) {
                // adjust clip to the left of the first column
                clip.x = 0;
            } else {
                // adjust clip to the right of the first column
                clip.x = totalColWidth;
            }
 
            // adjust clip to the top of the next set of rows
            clip.y += clip.height;
 
            // adjust clip width and height to be zero
            clip.width = 0;
            clip.height = 0;
 
            // fit as many rows as possible, and at least one
            int rowCount = table.getRowCount();
            int rowHeight = table.getRowHeight(row);
            do {
                clip.height += rowHeight;
 
                if (++row >= rowCount) {
                    break;
                }
 
                rowHeight = table.getRowHeight(row);
            } while (clip.height + rowHeight <= ph);
        }
 
        // we can short-circuit for JTable.PrintMode.FIT_WIDTH since
        // we'll always fit all columns on the page
        if (printMode == JTable.PrintMode.FIT_WIDTH) {
            clip.x = 0;
            clip.width = totalColWidth;
            return;
        }
 
        if (ltr) {
            // adjust clip to the left of the next set of columns
            clip.x += clip.width;
        }
 
        // adjust clip width to be zero
        clip.width = 0;
 
        // fit as many columns as possible, and at least one
        int colCount = table.getColumnCount();
        int colWidth = colModel.getColumn(col).getWidth();
        do {
            clip.width += colWidth;
            if (!ltr) {
                clip.x -= colWidth;
            }
 
            if (++col >= colCount) {
                // reset col to 0 to indicate we're finished all columns
                col = 0;
 
                break;
            }
 
            colWidth = colModel.getColumn(col).getWidth();
        } while (clip.width + colWidth <= pw);
 
    }
 
}
Merci d'avance pour l'aide