Printable not working properly - java

I have a system where the user can register students, subjects, and the student grade in each subject, together with the topic and the date. You can search a particular student grades in a particular subject by entering the code of the student, and by selecting the subject from a combobox. If you search it, those things are displayed in the jTable1.
Then, I have a PRINT button. When the user clicks the Print button, the content that is being displayed in the jTable1, goes to a jTable2, the difference between those 2 tables is that the jTable1 displays the name of the student, and the name of the subject, but the jTable2 doesn't. Here is a pic for better understanding:
http://i.stack.imgur.com/37SNh.png
So, when the user clicked the button to Print the jTable2, I was using this code right here:
MessageFormat header = new MessageFormat("Ficha Pedagógica - "+jComboBox1.getSelectedItem());
MessageFormat footer = new MessageFormat("Página {0,number,integer}");
try{
jTable2.print(JTable.PrintMode.NORMAL, header, null);
}
catch(java.awt.print.PrinterException e){
System.out.println("error");
}
The fact is, that I wanted 2 headlines to be printed, but such thing couldn't be achieved using the built-in print function. So, here in Stack Overflow, I found this topic:
How to print multiple header lines with MessageFormat using a JTable
After I found this, I tried using the code given there. Since I'm a beginner, even with all the comments in the code, I couldn't fully understand it. So, I tried to implement it, but now, when I click the "Print" button, nothing happens. This is my code of the Print button:
private void jButton4ActionPerformed(java.awt.event.ActionEvent evt) {
// TODO add your handling code here:
try{
Class.forName(driver);
con = DriverManager.getConnection(str_conn,usuario,senha);
stmt = con.createStatement();
sql = "select topico, nota, datanota from notas where notas.cod_aluno ="+jTextField1.getText()+" and notas.cod_curso ="+jTextField2.getText()+" order by notas.datanota";
rs = stmt.executeQuery(sql);
if(rs == null){
return;
}
ResultSetMetaData rsmd;
rsmd = rs.getMetaData();
Vector vetColuna = new Vector();
for(int i = 0;i<rsmd.getColumnCount();i++){
vetColuna.add(rsmd.getColumnLabel(i+1));
}
Vector vetLinhas = new Vector();
while(rs.next()){
Vector vetLinha = new Vector();
for(int i = 0;i<rsmd.getColumnCount();i++){
vetLinha.add(rs.getObject(i+1));
}
vetLinhas.add(vetLinha);
jTable2.setModel(new DefaultTableModel(vetLinhas,vetColuna));
}
}catch(ClassNotFoundException ex){
JOptionPane.showMessageDialog(null,"Erro\nNão foi possível carregar o driver.");
System.out.println("Nao foi possivel carregar o driver");
ex.printStackTrace();
}catch(SQLException ex){
JOptionPane.showMessageDialog(null,"Erro\nCertifique-se de que todos os\ncampos estejam preenchidos corretamente.");
System.out.println("Problema com o SQL");
ex.printStackTrace();
}
/*MessageFormat header = new MessageFormat("Ficha Pedagógica - "+jComboBox1.getSelectedItem());
MessageFormat footer = new MessageFormat("Página {0,number,integer}");
try{
jTable2.print(JTable.PrintMode.NORMAL, header, null);
}
catch(java.awt.print.PrinterException e){
System.out.println("gsgd");
}*/
DefaultTableModel dtm = new DefaultTableModel(new String[] { "Column 1" }, 1);
JTable jTable2 = new JTable(dtm) {
#Override
public Printable getPrintable(PrintMode printMode, MessageFormat headerFormat, MessageFormat footerFormat) {
return new TablePrintable(this, printMode, headerFormat, footerFormat);
}
};
}
The code for the "TablePrintable" class is the following:
static class TablePrintable implements Printable {
private final JTable table;
private final JTableHeader header;
private final TableColumnModel colModel;
private final int totalColWidth;
private final JTable.PrintMode printMode;
private final MessageFormat headerFormat;
private final MessageFormat footerFormat;
private int last = -1;
private int row = 0;
private int col = 0;
private final Rectangle clip = new Rectangle(0, 0, 0, 0);
private final Rectangle hclip = new Rectangle(0, 0, 0, 0);
private final Rectangle tempRect = new Rectangle(0, 0, 0, 0);
private static final int H_F_SPACE = 8;
private static final float HEADER_FONT_SIZE = 18.0f;
private static final float FOOTER_FONT_SIZE = 12.0f;
private final Font headerFont;
private final Font footerFont;
public TablePrintable(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);
}
#Override
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[] { Integer.valueOf(pageIndex + 1) };
// fetch the formatted header text, if any
String headerText = null;
if (headerFormat != null) {
headerText = headerFormat.format(pageNumber);
}
// fetch the formatted footer text, if any
String footerText = null;
if (footerFormat != null) {
footerText = footerFormat.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 = 0;
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);
int nbLines = headerText.split("\n").length;
hRect = graphics.getFontMetrics().getStringBounds(headerText, graphics);
hRect = new Rectangle2D.Double(hRect.getX(), Math.abs(hRect.getY()), hRect.getWidth(),
hRect.getHeight() * nbLines);
headerTextSpace = (int) Math.ceil(hRect.getHeight() * nbLines);
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 = graphics.getFontMetrics().getStringBounds(footerText, graphics);
footerTextSpace = (int) Math.ceil(fRect.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++;
}
// create a copy of the graphics so we don't affect the one given to
// us
Graphics2D g2d = (Graphics2D) graphics.create();
// translate into the co-ordinate system of the pageFormat
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);
String[] lines = footerText.split("\n");
printText(g2d, lines, fRect, footerFont, 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) {
String[] lines = headerText.split("\n");
printText(g2d, lines, hRect, headerFont, 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);
// dispose the graphics copy
g2d.dispose();
return PAGE_EXISTS;
}
private void printText(Graphics2D g2d, String[] lines, Rectangle2D rect, Font font, int imgWidth) {
g2d.setColor(Color.BLACK);
g2d.setFont(font);
for (int i = 0; i < lines.length; i++) {
int tx;
// if the text is small enough to fit, center it
if (rect.getWidth() < imgWidth) {
tx = (int) (imgWidth / 2 - g2d.getFontMetrics().getStringBounds(lines[i], g2d).getWidth() / 2);
// otherwise, if the table is LTR, ensure the left side of
// the text shows; the right can be clipped
} else if (table.getComponentOrientation().isLeftToRight()) {
tx = 0;
// otherwise, ensure the right side of the text shows
} else {
tx = -(int) (Math.ceil(rect.getWidth()) - imgWidth);
}
int ty = (int) Math.ceil(Math.abs(rect.getY() + i * rect.getHeight() / lines.length));
g2d.drawString(lines[i], tx, ty);
}
}
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);
}
}
But, like I said, when I click the "print" button, nothing happens. What could be going wrong?

With your newly modify JTable, you should only need to call it's print method.
DefaultTableModel dtm = new DefaultTableModel(new String[] { "Column 1" }, 1);
JTable jTable2 = new JTable(dtm) {
#Override
public Printable getPrintable(PrintMode printMode, MessageFormat headerFormat, MessageFormat footerFormat) {
return new TablePrintable(this, printMode, headerFormat, footerFormat);
}
};
try{
jTable2.print(JTable.PrintMode.NORMAL, header, null);
}
catch(java.awt.print.PrinterException e){
System.out.println("error");
}
Because you've overridden the getPrintable method to return your own implementation, this is what will be used to physically print the table...
Updated
The header text needs to be separated by a \n, for example...
MessageFormat header = new MessageFormat("Testing, 01\n02\n03");
Which can produce...
Updated
As near as I can tell, without been able to fully run the code, your print code should look something like...
private void jButton4ActionPerformed(java.awt.event.ActionEvent evt) {
Vector vetColuna = new Vector();
Vector vetLinhas = new Vector();
try {
Class.forName(driver);
con = DriverManager.getConnection(str_conn, usuario, senha);
stmt = con.createStatement();
sql = "select topico, nota, datanota from notas where notas.cod_aluno =" + jTextField1.getText() + " and notas.cod_curso =" + jTextField2.getText() + " order by notas.datanota";
rs = stmt.executeQuery(sql);
if (rs == null) {
return;
}
ResultSetMetaData rsmd;
rsmd = rs.getMetaData();
for (int i = 0; i < rsmd.getColumnCount(); i++) {
vetColuna.add(rsmd.getColumnLabel(i + 1));
}
while (rs.next()) {
Vector vetLinha = new Vector();
for (int i = 0; i < rsmd.getColumnCount(); i++) {
vetLinha.add(rs.getObject(i + 1));
}
vetLinhas.add(vetLinha);
}
} catch (ClassNotFoundException ex) {
JOptionPane.showMessageDialog(null, "Erro\nNão foi possível carregar o driver.");
System.out.println("Nao foi possivel carregar o driver");
ex.printStackTrace();
} catch (SQLException ex) {
JOptionPane.showMessageDialog(null, "Erro\nCertifique-se de que todos os\ncampos estejam preenchidos corretamente.");
System.out.println("Problema com o SQL");
ex.printStackTrace();
}
MessageFormat header = new MessageFormat("Ficha Pedagógica - " + jComboBox1.getSelectedItem() + "\nNome do Aluno - " + jTextField1.getText());
DefaultTableModel dtm = new DefaultTableModel(vetLinhas, vetColuna);
JTable jTable2 = new JTable(dtm) {
#Override
public Printable getPrintable(PrintMode printMode, MessageFormat headerFormat, MessageFormat footerFormat) {
return new TablePrintable(this, printMode, headerFormat, footerFormat);
}
};
try {
jTable2.setSize(jTable2.getPreferredSize());
JTableHeader tableHeader = jTable2.getTableHeader();
tableHeader.setSize(tableHeader.getPreferredSize());
jTable2.print(JTable.PrintMode.FIT_WIDTH);
} catch (PrinterException ex) {
ex.printStackTrace();
}
}

Related

One Row in One Page: Boxable

This is the code for this issue for you to check if there is any problem in the code.
Now the problem is when I limit the rows to 45 (this number fits in one page) every row will print in one page.
But, If I don't limit the rows and the row size (approximately 100-200), every row goes to new page in the PDF. The PDF page number goes to approximately equal to row numbers.
I have opened this issue in Boxable's git but it's not active so I came for help here.
Following are the files generated in both conditions:
LimitTemp.pdf
noLimitTemp.pdf
public class CSVtoPDF {
private float marginBetweenYElements = 10;
private float titleFontSize = 18;
private float fontSize = 8;
private float headerFontSize = 12;
private float header1FontSize = 14;
private float header2FontSize = 12;
private float headerCellHeight = 19;
private float dataCellHeight = 12;
private PDFont font = PDType1Font.HELVETICA;
private PDFont headerFont = PDType1Font.TIMES_BOLD;
List filteredData = new ArrayList();
ReportSettings rs = new ReportSettings();
String filePath, destPath, header1, header2, filename;
public CSVtoPDF(List data, Audit audit) throws IOException {
this.filteredData = data;
Date liveDate = new Date();
SimpleDateFormat format= new SimpleDateFormat("YYYY-MM-DD HH:mm:ss");
liveDate = Calendar.getInstance().getTime();
float headerCellHeight = 18;
PDDocument doc = new PDDocument();
PDPage page = new PDPage(PDRectangle.A4);
//page.setMediaBox(new PDRectangle(PDRectangle.A4.getHeight(),
// PDRectangle.A4.getWidth()));
PDPageContentStream cos = new PDPageContentStream(doc, page);
/* Add page to PDDocument */
doc.addPage(page);
System.out.println("Inside Main csvtopdf");
//Draw Header
Preferences prefs = Preferences.userRoot().node(this.getClass().getName());
try {
String[] keys = prefs.keys();
//destPath = prefs.get("destpath", rs.getDestPath());
//filename = prefs.get("file_name", rs.getFileName());
//header1 = prefs.get("header1", rs.getHeader1());
//header2 = prefs.get("header2", rs.getHeader2());
} catch (BackingStoreException ex) {
System.err.println(ex);
}
header1= "Header 1";
header2= "Header 2";
cos.beginText();
cos.moveTextPositionByAmount(220, 810);
cos.setFont(headerFont, header1FontSize);
cos.drawString(header1);
cos.endText();
cos.beginText();
cos.moveTextPositionByAmount(220, 800);
cos.setFont(headerFont, header2FontSize);
cos.drawString(header2);
cos.endText();
cos.beginText();
cos.moveTextPositionByAmount(220, 790);
cos.setFont(headerFont, headerFontSize);
cos.drawString("Report: Filtered Audit Report");
cos.endText();
//cos.beginText();
// cos.moveTo(200, 30);
//cos.setFont(headerFont, headerFontSize);
// cos.drawString(header2);
//cos.endText();
/* Initialize DataTable */
float margin = 20;
float tableWidth = page.getMediaBox().getWidth() - (2 * margin);
float yStartNewPage = page.getMediaBox().getHeight() - (2 * margin);
float yStart = yStartNewPage;
float bottomMargin = -800;
BaseTable table = new BaseTable(yStart, yStartNewPage,
bottomMargin, tableWidth, margin, doc, page, true, true);
Row<PDPage> dataRow = table.createRow(dataCellHeight);
for (int i = 0; i < data.size() - 1; i++) {
System.out.println(data.get(i));
}
drawTableData(table, dataCellHeight, 20, data, 1,doc,page);
table.draw();
File result;
if (Objects.isNull(destPath)) {
cos.close();
result = new File("temp.pdf");
} else {
result = new File(destPath);
}
System.out.println("befor save result");
doc.save(result);
System.out.println("after save result");
}
public void drawTableData(BaseTable table, float dataCellHeight, float
cellWidth, List<Audit> data, int style,PDDocument doc,PDPage page) {
String s;
Cell<PDPage> cell;
// for (int k = 0; k < data.size(); k++) {
System.out.println("inside drawtable for ");
for (int i = 0; i < data.size(); i++) { // add row
System.out.println("inside drawtable for " + i);
Audit atmp = data.get(i);
//if (i==35) {
// doc.addPage(page);
//}
Row<PDPage> sTableRow = table.createRow(dataCellHeight);
for (int j = 0; j <= 2; j++) { //add cell in the rows
if (j == 0) { // normal cells on right
s = atmp.getTimeStamp();
s = s.replaceAll("^\"|\"$", "");
cell = sTableRow.createCell(cellWidth, s, HorizontalAlignment.CENTER, VerticalAlignment.BOTTOM);
setStyle(style, cell);
//k++;
} else if (j == 1) { //big cells on left
s = atmp.getDiscription();
s = s.replaceAll("^\"|\"$", "");
cell = sTableRow.createCell(cellWidth + 50, s, HorizontalAlignment.CENTER, VerticalAlignment.BOTTOM);
setStyle(style, cell);
// k++;
} else if (j == 2) { //top blank cell
//System.out.println("In j null and 0 " + j);
s = atmp.getUserID();
s = s.replaceAll("^\"|\"$", "");
cell = sTableRow.createCell(cellWidth - 10, s, HorizontalAlignment.CENTER, VerticalAlignment.BOTTOM);
//cell.setBottomBorderStyle(null);
setStyle(style, cell);
//k++;
}
}
table.addHeaderRow(sTableRow);
System.out.println(" row added ");
}
//}
}
public void setStyle(int type, Cell cell) {
// type : 0 as header, 1 as table body
if (type == 0) {
cell.setFont(headerFont);
//cell.setHeight(headerCellHeight);
cell.setFontSize(headerFontSize);
cell.setBottomPadding(3);
} else if (type == 1) {
cell.setTopPadding(1);
cell.setFont(font);
cell.setAlign(HorizontalAlignment.LEFT);
//cell.setHeight(dataCellHeight);
cell.setFontSize(fontSize);
cell.setBottomPadding(1);
}
}
I found a silly problem in my code. I am telling this so that someone else must not repeat this.
I treated every row of the data table as header row. So it went to new page.
To be specific. In the function drawTableData I removed table.addHeaderRow(sTableRow)

Write text to image in multiple fonts with wrapping in java

I am trying to create an image with a given text and style. eg;
" textStyle(Offer ends 25/12/2016. Exclusions Apply., disclaimer) textStyle(See Details,underline) "
In above line i am splitting and creating a map that stores the first parameter of textStyle block as key and second parameter as value where second param defines the style to be applied on first param. Hence an entry of map will look like .
Now when i iterate over this map to write the text to image i check if the text is overflowing the width. If yes then it breaks the text and adds it to next line in the horizontal center. So for example lets say i am trying to write "Offer ends 25/12/2016. Exclusions Apply." with Arial and font size 12. While writing i find that i can write till "Offer ends 23/12/2016. " only and "Exclusions apply" has to go in next line. But it writes the text in horizontal center neglecting that as there is space left horizontally i can write "See Details" too in the same line.
Please help. Below is the code what i have tried. I have also tried creating a JTextPane and then converting it to image but this cannot be an option as it first creates the frame, makes it visible, writes it and then disposes it. And most of the times i was getting Nullpointer exception on SwingUtilities.invokeAndWait.
Actual : http://imgur.com/7aIlcEQ
Expected http://imgur.com/038zQTZ
public static BufferedImage getTextImage(String textWithoutStyle, Map<String, String> textToThemeMap, Properties prop, int height, int width) {
BufferedImage img = new BufferedImage(width,height,BufferedImage.TYPE_4BYTE_ABGR);
Graphics2D g2d = img.createGraphics();
g2d.setPaint(Color.WHITE);
FontMetrics fm = g2d.getFontMetrics();
Map<String, Font> textToFontMap = new LinkedHashMap<String, Font>();
for(Map.Entry<String, String> entry : textToThemeMap.entrySet()) {
if(StringUtils.isNotBlank(entry.getKey()) && StringUtils.isNotBlank(entry.getValue())) {
Font font = getFont(prop, entry.getValue().trim());
g2d.setFont(font);
fm = g2d.getFontMetrics();
String string = entry.getKey();
char[] chars = null;
int i = 0, pixelWidth = 0;
List<String> newTextList = new ArrayList<String>();
if(fm.stringWidth(string) > (width - 10)) {
chars = string.toCharArray();
for (i = 0; i < chars.length; i++) {
pixelWidth = pixelWidth + fm.charWidth(chars[i]);
if(pixelWidth >= (width - 10)) {
break;
}
}
String newString = WordUtils.wrap(string, i, "\n",false);
String[] splitString = newString.split("\n");
for(String str : splitString) {
newTextList.add(str);
textToFontMap.put(string, font);
}
} else {
newTextList.add(string);
textToFontMap.put(string, font);
}
}
}
Font font = new Font("Arial", Font.BOLD, 14);
int spaceOfLineHeight = (textToFontMap.size() - 1) * 7;
int spaceOfText = textToFontMap.size() * font.getSize();
int totalSpace = spaceOfLineHeight + spaceOfText ;
int marginRemaining = height - totalSpace;
int tempHt = marginRemaining / 2 + 10;
String txt = null;
for(Map.Entry<String, Font> entry : textToFontMap.entrySet()) {
txt = entry.getKey();
font = entry.getValue();
g2d.setFont(font);
fm = g2d.getFontMetrics();
int x = (width - fm.stringWidth(txt)) / 2;
int y = tempHt;
g2d.drawString(txt, x, y);
tempHt = tempHt + fm.getHeight();
}
// g2d.drawString(text.getIterator(), 0, (int)lm.getAscent() + lm.getHeight());
// g2d.dispose();
return img;
}
// Code with JTextPane ------------------------------------------
public static BufferedImage getTextImage(final Map < String, String > textToThemeMap, final Properties prop, final int height, final int width) throws Exception {
JFrame f = new JFrame();
f.setSize(width, height);
final StyleContext sc = new StyleContext();
DefaultStyledDocument doc = new DefaultStyledDocument(sc);
final JTextPane pane = new JTextPane(doc);
pane.setSize(width, height);
// Build the styles
final Paragraph[] content = new Paragraph[1];
Run[] runArray = new Run[textToThemeMap.size()];
int i = 0;
for (Map.Entry < String, String > entry: textToThemeMap.entrySet()) {
if (StringUtils.isNotBlank(entry.getValue().trim()) && StringUtils.isNotBlank(entry.getKey().trim())) {
Run run = new Run(entry.getValue().trim(), entry.getKey());
runArray[i++] = run;
}
}
content[0] = new Paragraph(null, runArray);
/*createDocumentStyles(sc, prop,textToThemeMap.values());
addText(pane, sc, sc.getStyle("default"), content);
pane.setEditable(false);*/
try {
SwingUtilities.invokeAndWait(new Runnable() {
public void run() {
try {
createDocumentStyles(sc, prop, textToThemeMap.values());
} catch (MalformedURLException e) {
//e.printStackTrace();
}
addText(pane, sc, sc.getStyle("default"), content);
pane.setEditable(false);
}
});
} catch (Exception e) {
System.out.println("Exception when constructing document: " + e);
}
f.getContentPane().add(pane);
f.setVisible(true);
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
BufferedImage img = new BufferedImage(width, height, BufferedImage.TYPE_4BYTE_ABGR);
Graphics2D gd = img.createGraphics();
f.paint(gd);
f.dispose();
/*ImageIO.write(img, "png", new File("C:\\Users\\spande0\\Desktop\\a.png"));
System.out.println("done");*/
return img;
}
I suspect the issue is in your 'Y' computation.
int spaceOfLineHeight = (newTextList.size() - 1) * 7;
int spaceOfText = newTextList.size() * font.getSize();
int totalSpace = spaceOfLineHeight + spaceOfText;
int marginRemaining = height - totalSpace;
int tempHt = marginRemaining / 2 + 10;
You have to keep the height occupied by the previous lines, and add it to the current 'Y'.
At the moment, for all the lines, the 'Y' values is same.
Declare prevHeight outside the for loop. and then do the following.
int tempHt = marginRemaining / 2 + 10;
tempHT += prevHeight;
prevHeight = tempHeight
Based on the comments, I will suggest you to break down your function into two smaller functions.
// Loop through the strings and find out how lines are split and calculate the X, Y
// This function will give the expected lines
splitLinesAndComputeResult
// Just render the lines
renderLines

Apache POI and Auto Row Height with merged cells

I'm using Apache POI and I am running into a weird problem. I can auto-size my rows, but only if there are no merged cells in that row. Here's an example:
new FileOutputStream('test.xlsx').withStream { OutputStream os ->
Workbook workbook = new XSSFWorkbook();
Sheet sheet = workbook.createSheet();
CellStyle wrapStyle = workbook.createCellStyle();
wrapStyle.setWrapText(true);
Row row = sheet.createRow(0); row.setRowStyle(wrapStyle);
Cell cell = row.createCell(0); cell.setCellStyle(wrapStyle);
cell.setCellValue("Very long text that needs to be wrapped")
cell = row.createCell(1); cell.setCellStyle(wrapStyle);
cell.setCellValue("Short text");
cell = row.createCell(2); cell.setCellStyle(wrapStyle);
cell.setCellValue("");
// These two lines break row auto-height!
//
CellRangeAddress cellRangeAddress = new CellRangeAddress(0, 0, 1, 2);
sheet.addMergedRegion(cellRangeAddress);
workbook.write(os);
}
This code generates the following document:
However, as soon as I comment out the lines that merge the two cells, the output looks like this:
Is this a bug? Does anyone know of a workaround?
By using the last part from Val Blant I've did something that's easier to use, and yet much complex.
Please be aware that there is a single line of code that adds one additional line to the cell height-wise, for personal reasons. If you do not wish that, please remove it. Also feel free to change it to a non-static, I've had to use static methods due to the company I'm working for making the specific class static.
PS: It's my first post on stackoverflow, please be gentle. :)
Solution:
public static Boolean isCellMerged(Cell cell) {
Sheet sheet = cell.getSheet();
for (CellRangeAddress mergedRegionRange : sheet.getMergedRegions()) {
Integer cellColumn = cell.getColumnIndex();
Integer cellRow = cell.getRowIndex();
if (mergedRegionRange.containsColumn(cellColumn) && mergedRegionRange.containsRow(cellRow)) {
return true;
}
}
return false;
}
public static List<List<Cell>> getCellsInRowsInsideRegionRange(Cell cell) {
Sheet sheet = cell.getSheet();
List<List<Cell>> mergedRowList = new ArrayList<>();
List<Cell> mergedCellsList = new ArrayList<>();
//Nejdříve musíme zjistit sloučenou sekci dané buňky
for (CellRangeAddress mergedRegionRange : sheet.getMergedRegions()) {
Integer cellColumn = cell.getColumnIndex();
Integer cellRow = cell.getRowIndex();
if (mergedRegionRange.containsColumn(cellColumn) && mergedRegionRange.containsRow(cellRow)) {
//Protože CellRangeAddress nemá moc metod, musíme si pomoci sami a získat z ní buňky a řádky
for (Row row : sheet) {
for (Cell iteratedCell : row) {
Integer iteratedCellColumn = iteratedCell.getColumnIndex();
Integer iteratedCellRow = iteratedCell.getRowIndex();
if (mergedRegionRange.containsColumn(iteratedCellColumn) && mergedRegionRange.containsRow(iteratedCellRow)) {
//Rozdělování jednotlivých řádků
//Není-li řádek bez buněk...
if (!mergedCellsList.isEmpty()) {
//Tak buňku přidáme do Listu buněk...
mergedCellsList.add(iteratedCell);
} else {
//Pokud se jedná o první buňku prvního řádku, tak přidáme rovnou
mergedCellsList.add(iteratedCell);
}
}
}
//Vložíme List buněk daného řádku do Listu řádků
if (!mergedCellsList.isEmpty()) {
mergedRowList.add(mergedCellsList);
}
//A vyresetujeme list buněk (začneme tak nanovo novým řádkem)
mergedCellsList = null;
mergedCellsList = new ArrayList<>();
}
//Vrátíme výsledný List řádků, obsahující Listy buněk ve sloučené sekci.
if (!mergedRowList.isEmpty()) {
return mergedRowList;
} else {
return null;
}
}
}
return null;
}
public static void adjustRowHeightForRowWithNonMergedCells(Row row) {
row.setHeight((short) -1);
}
public static void adjustRowHeightForRowWithMergedCells(Row row) {
Sheet sheet = row.getSheet();
Cell longestTextCell = null;
//Potřebujeme získat buňku s nejdelším textem
for (Cell iteratedCell : row) {
String iteratedTextString = iteratedCell.getStringCellValue();
if (longestTextCell != null && StringUtils.isNotBlank(longestTextCell.getStringCellValue())) {
if (iteratedTextString.length() > longestTextCell.getStringCellValue().length()) {
longestTextCell = iteratedCell;
}
} else {
longestTextCell = iteratedCell;
}
}
//Z textově nejobsáhlejší buňky potřebujeme dostat údaje
String longestText = "";
if (StringUtils.isNotBlank(longestTextCell.getStringCellValue()) && longestTextCell != null) {
longestText = longestTextCell.getStringCellValue();
//Protože textově nejobsáhlejší buňka nemusí nutně být sloučeného typu, je zapotřebí to všude ošetřit
Boolean isLongestTextCellMerged = isCellMerged(longestTextCell);
Float longestCellWidthInPixels = 0f;
Float longestMergedCellWidthInPixels = 0f;
//Získat šířku nesloučené nejobsáhlejší buňky je jednoduché
if (!isLongestTextCellMerged) {
Integer longestCellColumnIndex = longestTextCell.getColumnIndex();
longestCellWidthInPixels = sheet.getColumnWidthInPixels(longestCellColumnIndex);
} else {
//Musíme přijít na šířku sloučené buňky namísto buňky uvnitř sloučené buňky
List<List<Cell>> cellsInMergedRegion = getCellsInRowsInsideRegionRange(longestTextCell);
longestMergedCellWidthInPixels = 0f;
//Projdeme řádky
for (List<Cell> iteratedCell2List : cellsInMergedRegion) {
Float iteratedMergedCell2WidthInPixels = 0f;
//Projdeme jednotlivé buňky ve sloučené buňce na řádku a sečteme jejich šířky
for (Cell iteratedCell2 : iteratedCell2List) {
Integer iteratedCell2ColumnIndex = iteratedCell2.getColumnIndex();
Float iteratedCell2ColumnWidthInPixels = sheet.getColumnWidthInPixels(iteratedCell2ColumnIndex);
iteratedMergedCell2WidthInPixels = iteratedMergedCell2WidthInPixels + iteratedCell2ColumnWidthInPixels;
}
//Získáme šířku nejširší sloučené buňky na řádku
if (iteratedMergedCell2WidthInPixels > longestMergedCellWidthInPixels) {
longestMergedCellWidthInPixels = iteratedMergedCell2WidthInPixels;
}
//Resetujeme sčítání
iteratedMergedCell2WidthInPixels = 0f;
}
}
//Uložíme si nejširší buňku dle toho, zda je sloučená či nikoliv
Float longestWidthInPixels;
if (isLongestTextCellMerged) {
longestWidthInPixels = longestMergedCellWidthInPixels;
} else {
longestWidthInPixels = longestCellWidthInPixels;
}
//Potřebujeme font
Workbook wb = sheet.getWorkbook();
Short fontIndex = longestTextCell.getCellStyle().getFontIndex();
Font excelFont = wb.getFontAt(fontIndex);
//Potřebujeme i jeho styl
Integer excelFontStyle = java.awt.Font.PLAIN;
if (excelFont.getBold()) excelFontStyle = java.awt.Font.BOLD;
if (excelFont.getItalic()) excelFontStyle = java.awt.Font.ITALIC;
//Potřebujeme získat skutečný font i s velikostí
java.awt.Font currentFont = new java.awt.Font(excelFont.getFontName(), excelFontStyle, excelFont.getFontHeightInPoints());
//Získáme řetězec s vlastností
AttributedString attributedString = new AttributedString(longestText);
attributedString.addAttribute(TextAttribute.FONT, currentFont);
//Použijeme LineBreakMeasurer k zjištění kolik řádků bude text potřebovat
FontRenderContext fontRenderContext = new FontRenderContext(null, true, true);
LineBreakMeasurer measurer = new LineBreakMeasurer(attributedString.getIterator(), fontRenderContext);
Integer nextPosition = 0;
Integer lineCount = 0;
while (measurer.getPosition() < longestText.length()) {
nextPosition = measurer.nextOffset(longestWidthInPixels);
//Také musíme ošetřit případ manuálně zadaných LineBreaků pro všechny možné techtle mechtle :-S
String textLine = StringUtils.substring(longestText, measurer.getPosition(), nextPosition);
Boolean containsNewLine = StringUtils.containsIgnoreCase(textLine, "\r") || StringUtils.containsIgnoreCase(textLine, "\\r") || StringUtils.containsIgnoreCase(textLine, "\n") || StringUtils.containsIgnoreCase(textLine, "\\n");
if (containsNewLine) {
if (StringUtils.containsIgnoreCase(textLine, "\r\n") || StringUtils.containsIgnoreCase(textLine, "\\r\\n")) {
lineCount = lineCount + StringUtils.countMatches(textLine, "\n");
} else {
if (StringUtils.containsIgnoreCase(textLine, "\r") || StringUtils.containsIgnoreCase(textLine, "\\r")) {
lineCount = lineCount + StringUtils.countMatches(textLine, "\r");
}
if (StringUtils.containsIgnoreCase(textLine, "\n") || StringUtils.containsIgnoreCase(textLine, "\\n")) {
lineCount = lineCount + StringUtils.countMatches(textLine, "\n");
}
}
lineCount = lineCount + StringUtils.countMatches(textLine, "\\r?\\n");
}
lineCount++;
measurer.setPosition(nextPosition);
}
//Máme počet řádků, zbývá konečný dopočet výšky řádku a jeho použití
if (lineCount > 1) {
Float fontHeight = currentFont.getLineMetrics(longestText, fontRenderContext).getHeight();
//Pro jistotu přidáme jeden řádek navíc, člověk nikdy neví...
lineCount = lineCount + 1;
//Potřebujeme získat poslední řádek
Row lastRow = null;
if (isCellMerged(longestTextCell)) {
List<List<Cell>> mergedCellsInRows = getCellsInRowsInsideRegionRange(longestTextCell);
Integer lastRowInMergedSectionIndex = mergedCellsInRows.size() - 1;
List<Cell> lastRowInMergedSection = mergedCellsInRows.get(lastRowInMergedSectionIndex);
lastRow = lastRowInMergedSection.get(0).getRow();
} else {
lastRow = longestTextCell.getRow();
}
//Je potřeba ošetřit velikosti, pokud má sloučená buňka vícero řádků
Float cellsMergedAboveHeight = 0f;
if (isCellMerged(longestTextCell)) {
if (getCellsInRowsInsideRegionRange(longestTextCell).size() > 1) {
List<List<Cell>> mergedCellsInRows = getCellsInRowsInsideRegionRange(longestTextCell);
for (List<Cell> rowsWithCells : mergedCellsInRows){
if (!lastRow.equals(rowsWithCells.get(0).getRow())){
cellsMergedAboveHeight = cellsMergedAboveHeight + rowsWithCells.get(0).getRow().getHeight();
}
}
}
}
//Vzorec je ((Velikost fontu krát počet řádků plus (počet řádků krát volný prostor mezi řádky)) krát přepočet Excelu) mínus výška sloučených buněk nad posledním řádkem.
Short finalRowHeight = (short) (((fontHeight * lineCount + (lineCount * 15))* 10) - cellsMergedAboveHeight);
//A výsledek nastavíme na poslední řádek, protože jinak to przní sloupce vlevo a vpravo od vyšších řádků
lastRow.setHeight(finalRowHeight);
}
}
}
I was having a similar problem where row height was not adjusting for merged cells.
I had to write a custom function for adjusting height of that particular row. Here is my code:
I have fixed column width in my sheet to be 24, and default font size to be 11.
I needed adjustment in row height whenever my font size > 11 and cell text length is overflowing the column width or isn't visible properly due to larger length.
private void adjustRowHeightMergedCells(final XSSFCell mergedCell) {
DataFormatter dataFormatter = new DataFormatter();
int defaultCharWidth = SheetUtil.getDefaultCharWidth(mergedCell.getRow().getSheet().getWorkbook());
XSSFRow row = mergedCell.getRow();
// Getting merged cell width value
double cellValueWidth = SheetUtil.getCellWidth(mergedCell, defaultCharWidth, dataFormatter, true);
// If cell width value > 24 (Default value), calculate how much extra row height is needed
// This happends when text length is larger than the column width (24)
float extraRowHeightDueToCellTextLength = (float) Math.floor(cellValueWidth / 24) * row.getHeightInPoints();
float extraRowHeightDueToCellTextFontSize = 0;
// If cell font size > 11 (Default value), calculate how much extra row height is needed
short cellTextFontSize = mergedCell.getCellStyle().getFont().getFontHeightInPoints();
if (cellTextFontSize > 11) {
extraRowHeightDueToCellTextFontSize = (cellTextFontSize-ExcelConstants.DEFAULT_FONT_SIZE) * (5f/3f);
}
// 5f/3f in above calculation is custom number which assumed by thinking that for font size 11, my row height shud be 15, and for example custom font size 20, row height shud be 30, hence the factor 5f/ 3f( per extra 1 point increase in font size above 11, row height shud be increased by 5/3)
// Larger of two adjustment values will be taken and added to current row height
float extraRowHeightAdjustment = Math.max(extraRowHeightDueToCellTextFontSize,extraRowHeightDueToCellTextLength);
if(extraRowHeightAdjustment > 0) {
row.setHeightInPoints(row.getHeightInPoints() + extraRowHeightAdjustment);
}
}
Kinda hacky solution but works for my situation, you can modify it per your requirements.
After more research, turns out that this is a problem with Excel itself, not POI. Excel does indeed lose its ability to auto-fit rows to content for all rows that have merged cells in them. For more info see:
http://excel.tips.net/T003207_Automatic_Row_Height_For_Merged_Cells_with_Text_Wrap.html
http://blog.contextures.com/archives/2012/06/07/autofit-merged-cell-row-height/
The workaround is based on predicting the number of lines in the largest cell of the row, and then adjusting the row height manually. The code is based on this discussion:
http://mail-archives.apache.org/mod_mbox/poi-user/200906.mbox/%3C24216153.post#talk.nabble.com%3E
RowInfo and NestedCellInfo below are my custom data structures that keep track of the sheet layout. You should be able to replace these with your equivalents and helper functions.
private void adjustRowHeights(Sheet sheet, List<RowInfo> rows, SortedSet<Integer> createdColumnNumbers) {
SortedMap<Integer, Float> columnWidthsInPx = [] as TreeMap;
createdColumnNumbers.each {
columnWidthsInPx.put(it, sheet.getColumnWidthInPixels(it));
}
rows.each { RowInfo rowInfo ->
if ( rowInfo.hasMergedCells ) {
Row excelRow = sheet.getRow(rowInfo.rowIndex);
// Find the column with the longest text - that's the one that will determine
// the row height
//
NestedCellInfo longestCell = rowInfo.getCellWithLongestContent();
String cellText = longestCell.getText();
if ( cellText != null && cellText.size() > 5 ) {
int colIdx = rowInfo.cells.indexOf(longestCell);
// Figure out available width in pixels, taking colspans into account
//
float columnWidthInPx = columnWidthsInPx[colIdx];
int numberOfMergedColumns = longestCell.colSpan;
(numberOfMergedColumns - 1).times {
columnWidthInPx += columnWidthsInPx[colIdx + it];
}
// Setup the font we'll use for figuring out where the text will be wrapped
//
XSSFFont cellFont = longestCell.getCellFont();
int fontStyle = Font.PLAIN;
if ( cellFont.getBold() ) fontStyle = Font.BOLD;
if ( cellFont.getItalic() ) fontStyle = Font.ITALIC;
java.awt.Font currFont = new java.awt.Font(
cellFont.getFontName(),
fontStyle,
cellFont.getFontHeightInPoints());
AttributedString attrStr = new AttributedString(cellText);
attrStr.addAttribute(TextAttribute.FONT, currFont);
// Use LineBreakMeasurer to count number of lines needed for the text
//
FontRenderContext frc = new FontRenderContext(null, true, true);
LineBreakMeasurer measurer = new LineBreakMeasurer(attrStr.getIterator(), frc);
int nextPos = 0;
int lineCnt = 0;
while (measurer.getPosition() < cellText.length()) {
nextPos = measurer.nextOffset( columnWidthInPx );
lineCnt++;
measurer.setPosition(nextPos);
}
if ( lineCnt > 1 ) {
excelRow.setHeight((short)(excelRow.getHeight() * lineCnt * /* fudge factor */ 0.7));
}
}
}
}
This solution is far from perfect, but it allowed me to move forward.

Printing a text document using Java

Alright, I have made a program that makes a text file. The text file is a different size every time the program is ran. I simply just want to add a print button that allows the user to print out the text file to a printer. I made a button with an action listener that brings up my print class. It is almost working except it only prints one page with my text displayed in horizontal columns extremely small. I think my problem has something to do with my printJob setup. Any help would be greatly appreciated.
public class PrintingClass implements Printable {
// Global variables
int[] pageBreaks;
String [] textLines;
static String fileName;
public static void print(String filename){
fileName = filename;
PrintingClass object = new PrintingClass();
PrinterJob job = PrinterJob.getPrinterJob();
job.setPrintable(object);
Boolean ok = job.printDialog();
if (ok) {
try {
job.print();
} catch (PrinterException ex) {
/* The job did not successfully complete */
}
}
}
public int print(Graphics g, PageFormat pf, int pageIndex)
throws PrinterException {
Font font = new Font("Monospaced", Font.PLAIN, 12);
FontMetrics metrics = g.getFontMetrics(font);
int lineHeight = metrics.getHeight();
if (pageBreaks == null) {
initTextLines();
int linesPerPage = (int)(pf.getImageableHeight()/lineHeight);
System.out.println("Lines per page = " + linesPerPage);
int numBreaks = (textLines.length-1)/linesPerPage;
System.out.println("number of pages = " + numBreaks);
pageBreaks = new int[numBreaks];
for (int b=0; b<numBreaks; b++) {
pageBreaks[b] = (b+1)*linesPerPage;
}
}
if (pageIndex > pageBreaks.length) {
return NO_SUCH_PAGE;
}
/* User (0,0) is typically outside the imageable area, so we must
* translate by the X and Y values in the PageFormat to avoid clipping
* Since we are drawing text we
*/
Graphics2D g2d = (Graphics2D)g;
g2d.translate(pf.getImageableX(), pf.getImageableY());
/* Draw each line that is on this page.
* Increment 'y' position by lineHeight for each line.
*/
int y = 0;
int start = (pageIndex == 0) ? 0 : pageBreaks[pageIndex-1];
int end = (pageIndex == pageBreaks.length)
? textLines.length : pageBreaks[pageIndex];
for (int line=start; line<end; line++) {
y += lineHeight;
g.drawString(textLines[line], 0, y);
}
/* tell the caller that this page is part of the printed document */
return PAGE_EXISTS;
}
/**
* This will initialize the textLines[] variable
* and read in my file
* #param fileName
*/
public void initTextLines(){
// Get file size
int fileSize = counter();
// Initialize textLine
textLines = new String[fileSize];
// Read text to set lines
BufferedReader file;
try {
file = new BufferedReader(new FileReader(fileName));
String line = null;
int x = 0;
while((line = file.readLine()) != null){
textLines[x] = line;
x++;
}
}
catch (FileNotFoundException e) {
e.printStackTrace();
}
catch (IOException e) {
e.printStackTrace();
}
}
/**
* This will simply count the size of the file
* and return it
* #return
*/
public int counter(){
int count = 0;
try {
BufferedReader file = new BufferedReader(new FileReader(fileName));
while(file.readLine() != null){
count++;
}
file.close();
} catch (IOException e) {
e.printStackTrace();
}
return count;
}
}
Most of this code comes straight from Javas own tutorial page. Thank you.

Printing Multiple pages in JAVA

So I was tinkering with this code that I found http://docs.oracle.com/javase/tutorial/2d/printing/examples/PaginationExample.java
I altered the page size to 300, 400 when I tried printing to XPS the first page is always default and the following is 300,400, I want to is set all printed pages to 300,400
below is the code
package app;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import java.awt.print.*;
public class PaginationExample implements Printable, ActionListener {
int[] pageBreaks; // array of page break line positions.
/* Synthesise some sample lines of text */
String[] textLines;
private void initTextLines() {
if (textLines == null) {
int numLines = 200;
textLines = new String[numLines];
for (int i = 0; i < numLines; i++) {
textLines[i] = "This is line number " + i;
}
}
}
public int print(Graphics g, PageFormat pf, int pageIndex)
throws PrinterException {
pf.setPaper(paper);
Font font = new Font("Serif", Font.PLAIN, 10);
FontMetrics metrics = g.getFontMetrics(font);
int lineHeight = metrics.getHeight();
if (pageBreaks == null) {
initTextLines();
int linesPerPage = (int) (pf.getImageableHeight() / lineHeight);
int numBreaks = (textLines.length - 1) / linesPerPage;
pageBreaks = new int[numBreaks];
for (int b = 0; b < numBreaks; b++) {
pageBreaks[b] = (b + 1) * linesPerPage;
}
}
if (pageIndex > pageBreaks.length) {
return NO_SUCH_PAGE;
}
/* User (0,0) is typically outside the imageable area, so we must
* translate by the X and Y values in the PageFormat to avoid clipping
* Since we are drawing text we
*/
Graphics2D g2d = (Graphics2D) g;
g2d.translate(pf.getImageableX(), pf.getImageableY());
/* Draw each line that is on this page.
* Increment 'y' position by lineHeight for each line.
*/
int y = 0;
int start = (pageIndex == 0) ? 0 : pageBreaks[pageIndex - 1];
int end = (pageIndex == pageBreaks.length)
? textLines.length : pageBreaks[pageIndex];
for (int line = start; line < end; line++) {
y += lineHeight;
g.drawString(textLines[line], 0, y);
}
/* tell the caller that this page is part of the printed document */
return PAGE_EXISTS;
}
public void actionPerformed(ActionEvent e) {
PrinterJob job = PrinterJob.getPrinterJob();
job.setPrintable(this);
boolean ok = job.printDialog();
if (ok) {
try {
job.print();
} catch (PrinterException ex) {
/* The job did not successfully complete */
}
}
}
private static Paper paper;
public static void main(String args[]) {
paper = new Paper();
paper.setSize(300, 400);
try {
String cn = UIManager.getSystemLookAndFeelClassName();
UIManager.setLookAndFeel(cn); // Use the native L&F
} catch (Exception cnf) {
}
JFrame f = new JFrame("Printing Pagination Example");
f.addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e) {
System.exit(0);
}
});
JButton printButton = new JButton("Print Pages");
printButton.addActionListener(new PaginationExample());
f.add("Center", printButton);
f.pack();
f.setVisible(true);
}
}
Try to use the Book class which is used in this thread.
Book pBook = new Book();
pBook.append(this, pPageFormat);
pPrinterJob.setPageable(pBook);
pPrinterJob.print();

Categories