Printing a large Swing component
Since a component in a JScrollPane can have arbitrary size, even after it is made displayable, My solution is to try this:
JPanel c = createPanel();
JFrame f = new JFrame();
f.getContentPane().add(new JScrollPane(c));
f.pack();
print(c);
so that I can validate the JPanel without it being size-limited to the maximum size of a JFrame. It also has the "unlimited resolution" look on the fonts and things that you get from printing the components directly, without double-buffering like trashgod suggested.
How to print whole JPanel with a footer in every page in java swing
So based on this example which demonstrates how to print a component across multiple pages, I modified it to allow for the printing of a footer.
This example draws directly via the Graphics
context, but conceptually, the process would be simple enough to paint using a supplied JComponent
of some sort.
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Rectangle;
import java.awt.Shape;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.geom.Rectangle2D;
import java.awt.image.BufferedImage;
import java.awt.print.PageFormat;
import java.awt.print.Printable;
import static java.awt.print.Printable.NO_SUCH_PAGE;
import static java.awt.print.Printable.PAGE_EXISTS;
import java.awt.print.PrinterException;
import java.awt.print.PrinterJob;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
import javax.print.attribute.HashPrintRequestAttributeSet;
import javax.print.attribute.PrintRequestAttributeSet;
import javax.print.attribute.standard.MediaSizeName;
import javax.print.attribute.standard.PrinterResolution;
import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.Scrollable;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
public class PrintMe {
public static void main(String[] args) {
new PrintMe();
}
public PrintMe() {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
ex.printStackTrace();
}
TestPane testPane = new TestPane();
JButton btn = new JButton("Print");
btn.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
PrintRequestAttributeSet aset = new HashPrintRequestAttributeSet();
aset.add(MediaSizeName.ISO_A4);
aset.add(new PrinterResolution(300, 300, PrinterResolution.DPI));
PrinterJob pj = PrinterJob.getPrinterJob();
pj.setPrintable(new MultiPagePrintable(testPane));
if (pj.printDialog(aset)) {
try {
pj.print(aset);
testPane.getParent().invalidate();
testPane.getParent().validate();
} catch (PrinterException ex) {
ex.printStackTrace();
}
}
}
});
JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(new JScrollPane(testPane));
frame.add(btn, BorderLayout.SOUTH);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class TestPane extends JPanel implements Scrollable {
private BufferedImage img;
public TestPane() {
try {
img = ImageIO.read(some image source);
} catch (IOException ex) {
ex.printStackTrace();
}
}
@Override
public Dimension getPreferredSize() {
return img == null ? new Dimension(200, 200) : new Dimension(img.getWidth(), img.getHeight());
}
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
if (img != null) {
Graphics2D g2d = (Graphics2D) g.create();
int x = (getWidth() - img.getWidth()) / 2;
int y = (getHeight() - img.getHeight()) / 2;
g2d.drawImage(img, x, y, this);
g2d.dispose();
}
}
@Override
public Dimension getPreferredScrollableViewportSize() {
return new Dimension(200, 200);
}
@Override
public int getScrollableUnitIncrement(Rectangle visibleRect, int orientation, int direction) {
return 128;
}
@Override
public int getScrollableBlockIncrement(Rectangle visibleRect, int orientation, int direction) {
return 128;
}
@Override
public boolean getScrollableTracksViewportWidth() {
return false;
}
@Override
public boolean getScrollableTracksViewportHeight() {
return false;
}
}
public class MultiPagePrintable implements Printable {
private JComponent component;
private int lastPage = 0;
private double yOffset;
private Font footerFont;
public MultiPagePrintable(JComponent component) {
this.component = component;
footerFont = new Font("Arial", Font.BOLD, 24);
}
@Override
public int print(Graphics graphics, PageFormat pageFormat, int pageIndex) throws PrinterException {
int result = NO_SUCH_PAGE;
String name = "I be mighty!";
String page = Integer.toString(pageIndex);
FontMetrics fm = graphics.getFontMetrics(footerFont);
double footerHeight = fm.getHeight() + 4;
double height = pageFormat.getImageableHeight() - footerHeight;
component.setSize(component.getPreferredSize());
if (lastPage != pageIndex) {
lastPage = pageIndex;
yOffset = height * pageIndex;
if (yOffset > component.getHeight()) {
yOffset = -1;
}
}
if (yOffset >= 0) {
Graphics2D g2d = (Graphics2D) graphics.create();
g2d.translate((int) pageFormat.getImageableX(),
(int) pageFormat.getImageableY());
g2d.translate(0, -yOffset);
component.printAll(g2d);
g2d.translate(0, +yOffset);
Shape footerArea = new Rectangle2D.Double(0, height, pageFormat.getImageableWidth(), footerHeight);
g2d.setColor(Color.WHITE);
g2d.fill(footerArea);
g2d.setColor(Color.RED);
g2d.draw(footerArea);
g2d.setColor(Color.BLACK);
g2d.translate(0, (pageFormat.getImageableHeight() - footerHeight));
float x = 2;
float y = (float)((footerHeight - fm.getHeight()) / 2d);
g2d.drawString(name, x, y + fm.getAscent());
x = (float)(pageFormat.getImageableWidth() - fm.stringWidth(page) - 2);
g2d.drawString(page, x, y + fm.getAscent());
g2d.dispose();
result = PAGE_EXISTS;
}
return result;
}
}
}
JTable column labels not printing
Okay, after much screwing around, I got "something" to work. The "core" problems seem to come down to
- Creating multiple instance of the
JTable
- "add" the
JTable
to theJScrollPane
(scroller.add(setupTable());
), as apposed to setting it as the screen pane's viewport's view - Addition, unnecessary UI elements which just made it more difficult to understand the code then was required
This example just dumps the output to a file, but it should work just fine for printing.
import java.awt.Color;
import java.awt.Component;
import static java.awt.Dialog.ModalityType.APPLICATION_MODAL;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.Graphics2D;
import java.awt.Insets;
import java.awt.Rectangle;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.image.BufferedImage;
import java.awt.print.PageFormat;
import java.awt.print.Paper;
import java.awt.print.Printable;
import java.io.File;
import java.io.IOException;
import java.sql.Connection;
import java.text.MessageFormat;
import javax.imageio.ImageIO;
import javax.print.attribute.HashPrintRequestAttributeSet;
import javax.print.attribute.PrintRequestAttributeSet;
import javax.print.attribute.standard.MediaPrintableArea;
import javax.swing.BoxLayout;
import javax.swing.JButton;
import javax.swing.JDialog;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import static javax.swing.WindowConstants.DISPOSE_ON_CLOSE;
import javax.swing.table.DefaultTableCellRenderer;
import javax.swing.table.DefaultTableModel;
public class PrintPreview extends JDialog implements ActionListener {
public static void main(String[] args) {
new PrintPreview(new int[]{1, 2, 3, 4}, null);
}
private JTable infoTable;
private boolean printed;
private int windowWidth;
private int windowHeight;
JPanel container;
// JPanel scrollerPanel;
JPanel dataPanel;
private int[] idList;
private Connection conn;
private JScrollPane scroller;
private JButton printButton;
JTable printable;
public PrintPreview(int[] tIds, Connection tConn) {
container = new JPanel();
container.setLayout(new BoxLayout(container, BoxLayout.Y_AXIS));
printed = false;
idList = tIds;
conn = tConn;
setupFrame();
setupScroller();
setupButtons();
this.setContentPane(container);
this.pack();
this.setVisible(true);
}
//returns true if printed, false otherwise
public boolean getCloseValue() {
return printed;
}
private void setupFrame() {
this.setTitle("Edit Data");
this.setSize(800, 700); //Width, Height
this.setLocationRelativeTo(null); //Centers the JFrame on the screen
this.setLayout(new BoxLayout(this.getContentPane(), BoxLayout.Y_AXIS));
// this.setResizable(false);
this.setModalityType(APPLICATION_MODAL);
this.setDefaultCloseOperation(DISPOSE_ON_CLOSE);
//Gets the size of the contentPanel of the frame
Insets inset = this.getInsets();
windowWidth = this.getSize().width - (inset.left + inset.right);
windowHeight = this.getSize().height - (inset.top + inset.bottom);
}
private void setupScroller() {
// scrollerPanel = new JPanel();
scroller = new JScrollPane(setupTable());
// scroller = new JScrollPane(setupTable(), JScrollPane.VERTICAL_SCROLLBAR_ALWAYS,
// JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
// infoTable.setFillsViewportHeight(true);
// scroller.setSize(windowWidth, windowHeight - 120);
// scroller.setMinimumSize(new Dimension(windowWidth, windowHeight - 120));
// scroller.setMaximumSize(new Dimension(windowWidth, windowHeight - 120));
// scroller.setPreferredSize(new Dimension(windowWidth, windowHeight - 120));
// scroller.setVisible(true);//*********************************************************
// scroller.add(setupTable());
// scrollerPanel.add(scroller);
// scrollerPanel.setVisible(true);//******************************************************
// scrollerPanel.setOpaque(true);//*************************************************************
container.add(scroller);
}
private void setupButtons() {
JPanel spacer1 = new JPanel();
spacer1.setSize(100, 20);
spacer1.setMaximumSize(new Dimension(100, 20));
spacer1.setMinimumSize(new Dimension(100, 20));
spacer1.setPreferredSize(new Dimension(100, 20));
JPanel spacer2 = new JPanel();
spacer2.setSize(100, 20);
spacer2.setMaximumSize(new Dimension(100, 20));
spacer2.setMinimumSize(new Dimension(100, 20));
spacer2.setPreferredSize(new Dimension(100, 20));
printButton = new JButton("Print");
printButton.setFont((new Font("", Font.BOLD, 14)));
printButton.setSize(new Dimension(130, 35));
printButton.setMaximumSize(new Dimension(130, 35));
printButton.setMinimumSize(new Dimension(130, 35));
printButton.setPreferredSize(new Dimension(130, 35));
printButton.addActionListener(this);
spacer1.setAlignmentX(Component.CENTER_ALIGNMENT);
printButton.setAlignmentX(Component.CENTER_ALIGNMENT);
container.add(spacer1);
container.add(printButton);
container.add(spacer2);
}
private JTable setupTable() {
infoTable = new JTable();
DefaultTableModel dm = new DefaultTableModel(0, 0);
String header[] = new String[]{"Case #", "Date", "Officer #", "Offence",
"Description", "Report"};
dm.setColumnIdentifiers(header);
infoTable.setModel(dm);
infoTable.setRowHeight(26);
infoTable.setFocusable(false);//display only
//Adds everything to the table
int idSize = idList.length;
for (int row = 0; row < 10; row++) {
String value = Integer.toString(row);
String[] values = new String[]{value, value, value, value, value, value};
dm.addRow(values);
}
// for (int x = 0; x < idSize; x++) {
// try {
// String[] values = getInfo(idList[x]);
// values[4] = values[4].trim();
// values[4] = values[4].replaceAll("<html>", "");
//
// dm.addRow(values);
// } catch (SQLException e) {
// System.out.println("Error: " + e);
// System.out.println("Event-addObjects(): Problem with getting event info");
// }
//
// infoTable.setFont(new Font("Serif", Font.PLAIN, 10));
// }
//Centers the values on the smaller columns
// DefaultTableCellRenderer centerRenderer = new DefaultTableCellRenderer();
// centerRenderer.setHorizontalAlignment(JLabel.CENTER);
// infoTable.getColumnModel().getColumn(0).setCellRenderer(centerRenderer);
// infoTable.getColumnModel().getColumn(1).setCellRenderer(centerRenderer);
// infoTable.getColumnModel().getColumn(2).setCellRenderer(centerRenderer);
// infoTable.getColumnModel().getColumn(3).setCellRenderer(centerRenderer);
// infoTable.getColumnModel().getColumn(5).setCellRenderer(centerRenderer);
//
// //Sets the sizes of the columns
// infoTable.getColumnModel().getColumn(0).setMinWidth(40);
// infoTable.getColumnModel().getColumn(1).setMinWidth(65);
// infoTable.getColumnModel().getColumn(2).setMinWidth(40);
// infoTable.getColumnModel().getColumn(3).setMinWidth(80);
// infoTable.getColumnModel().getColumn(4).setMinWidth(250);
// infoTable.getColumnModel().getColumn(5).setMinWidth(50);
//Makes the Description column cells JTextFields
// infoTable.getColumnModel().getColumn(4).setCellRenderer(new VariableRowHeightRenderer());
//Looks at the size each JTextField would like to be and changes the rows to accomidate
// int column = 4;
// for (int row = 0; row < infoTable.getRowCount(); row++) {
// int rowHeight = 26;
//
// Component comp = infoTable.prepareRenderer(infoTable.getCellRenderer(row, column), row, column);
// rowHeight = Math.max(rowHeight, comp.getPreferredSize().height);
//
// if (rowHeight != infoTable.getRowHeight(row)) {
// infoTable.setRowHeight(row, rowHeight);
// }
// }
// infoTable.setVisible(true);//***********************************************************************
return infoTable;
}
@Override
public void actionPerformed(ActionEvent e) {
String cmd = e.getActionCommand();
switch (cmd) {
case "Print":
printed = true;
//Makes the margins smaller
PrintRequestAttributeSet aset = new HashPrintRequestAttributeSet();
aset.add(new MediaPrintableArea((float) 8.25, (float) 10.0, (float) 8.5, (float) 11.0, MediaPrintableArea.INCH));
MessageFormat empty = new MessageFormat("");
MessageFormat footerFormat = new MessageFormat("- {0} -");
// printable.print(PrintMode.FIT_WIDTH, empty, footerFormat, true, aset, false);
Paper paper = new Paper();
paper.setImageableArea(0, 0, 700, 890);
paper.setSize(700, 890);
PageFormat format = new PageFormat();
format.setPaper(paper);
format.setOrientation(PageFormat.PORTRAIT);
// printjob.setPrintable(printable, format);
BufferedImage img = new BufferedImage(700, 890, BufferedImage.TYPE_INT_RGB);
Graphics2D g2d = img.createGraphics();
g2d.setColor(Color.WHITE);
g2d.fill(new Rectangle(0, 0, 890, 700));
Printable printable = infoTable.getPrintable(JTable.PrintMode.FIT_WIDTH, null, null);
try {
printable.print(g2d, format, 0);
} catch (Exception exp) {
exp.printStackTrace();
}
g2d.dispose();
try {
ImageIO.write(img, "png", new File("Print.png"));
} catch (IOException ex) {
ex.printStackTrace();
}
//this.dispose();
break;
default:
break;
}
}
}
Is jTable suitable for printing reports in java desktop application?
we have previously used Apache FOP (https://xmlgraphics.apache.org/fop/) and jasper Reports(http://community.jaspersoft.com/project/jasperreports-library).
both of them use XMl templates and you could Fill Data and extract various report formats (i.e. RTF, PDF, html).
Related Topics
Accessing Post Variables Using Java Servlets
Building an Uberjar with Gradle
Creating New Generic Object with Wildcard
Jce Cannot Authenticate the Provider Bc in Java Swing Application
Java - How to Create New Entry (Key, Value)
Stringbuilder/Stringbuffer VS. "+" Operator
What's the Use of Session.Flush() in Hibernate
Maximum Size of Hashset, Vector, Linkedlist
Jframe.Dispose() VS System.Exit()
How Does the Java Array Argument Declaration Syntax "..." Work