JTable 打印。如何以编程方式设置分页符?
JTable Printing. How to set page breaks programmatically?
我正在尝试找到一种以编程方式设置分页符以打印出 JTable 的方法。
例如,我有一个 table 大约有 150 行,如下所示:
行号Data1 Data2 Data3 …等
1 a b c d
1 a b c d
1 a b c d
2 a b c d
2 a b c d
3 a b c d
3 a b c d
3 a b c d
3 a b c d
4 a b c d
5 a b c d
5 a b c d
5 a b c d
…等 …等…等…等…等
我需要想办法在行号改变时开始打印新的一页。
我找到了 printing selected rows 的方法,到目前为止已经修改它以循环遍历我的 table 将行添加到临时打印模型,然后在重置之前调用 print() 方法进行打印临时变量。但是,这意味着我可能调用 print() 10 次,每个行号调用一次,这是一个 unacceptable 解决方案。完成当前漏洞解决方案的代码如下:
btnPrint.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent arg0) {
try {
int wrappingLineNumber = (Integer) table.getValueAt(0, 0);
WrappingSheetsTableModel printModel = new WrappingSheetsTableModel();
for (int i = 0; i < table.getRowCount(); i++) {
if ((Integer)table.getValueAt(i, 0) == wrappingLineNumber) {
System.out.println(table.getValueAt(i, -1));
printModel.addRow((WrappingSheets) table.getValueAt(i, -1));
} else {
wrappingLineNumber = (Integer) table.getValueAt(i, 0);
// if not the same, i.e., value changed
JTable toPrint = new JTable(printModel);
toPrint.setSize(toPrint.getPreferredSize());
JTableHeader tableHeader = toPrint.getTableHeader();
tableHeader.setSize(tableHeader.getPreferredSize());
toPrint.print(JTable.PrintMode.FIT_WIDTH);
printModel.removeAll();
printModel.addRow((WrappingSheets) table.getValueAt(i, -1));
}
}
System.out.println("success printing");
} catch (PrinterException pe) {
System.out.println("printing failed");
pe.printStackTrace();
}
};
});
任何人都可以提供更好的解决方案,只要行号列中的值发生变化,就会在新页面上开始打印吗?
非常感谢您提供的任何帮助!
经过进一步的研究和思考,我意识到可以创建 sub-tables/temporary tables 只保存与每条换行相关的信息。接下来的问题是如何将多个 JTable 作为一个打印作业进行打印。已提出并回答了此问题的变体 here and particularly here。根据第二个 link 中提供的信息,我想出的解决方案如下:
解决方案使用 Durandal 在上面的 link 2 中提供的未更改的 PrintableWrapper,包含在此处仅供参考 "to spare us the hassle of iterating over each page":
public class PrintableWrapper implements Printable {
private Printable delegate;
private int offset;
public PrintableWrapper(Printable delegate, int offset) {
this.offset = offset;
this.delegate = delegate;
}
@Override
public int print(Graphics graphics, PageFormat pageFormat, int pageIndex) throws PrinterException {
return delegate.print(graphics, pageFormat, pageIndex-offset);
}}
解决方案还利用相同 link 中未更改的 kleopatra / Durandal 代码来获取每个 table 所需的页数:
public int getNumberOfPages(Printable delegate, PageFormat pageFormat) throws PrinterException {
Graphics g = new BufferedImage(1, 1, BufferedImage.TYPE_INT_RGB).createGraphics();
int numPages = 0;
while (true) {
int result = delegate.print(g, pageFormat, numPages);
if (result == Printable.PAGE_EXISTS) {
++numPages;
} else {
break;
}
}
return numPages;
}
据此,解决方案是创建 PrinterJob、Book 和临时 JTable。然后把临时的table加到书里,用上面的class和方法。最后打印这本书。此解决方案的当前代码可以在下面找到,代码中包含解释性注释:
btnPrint.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent arg0) {
try {
//Code revised from
// \/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/
PrinterJob printerJob = PrinterJob.getPrinterJob();
//Set 1/4 " margins and orientation
PageFormat pf = printerJob.defaultPage();
pf.setOrientation(PageFormat.LANDSCAPE);
Paper paper = new Paper();
//double margin = 36; // half inch
double margin = 18; // quarter inch
paper.setImageableArea(margin, margin, paper.getWidth() - margin * 2, paper.getHeight() - margin * 2);
pf.setPaper(paper);
Book bookToPrint = new Book();
// /\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\
//Code revised from
// List to store temporary tables to print
List<JTable> tablesToPrint = new ArrayList<JTable>();
// create temporary print tables by wrapping line number
int wrappingLineNumber = (Integer) table.getValueAt(0, 0);
WrappingSheetsTableModel printModel = new WrappingSheetsTableModel();
for (int i = 0; i < table.getRowCount(); i++) {
if ((Integer)table.getValueAt(i, 0) == wrappingLineNumber) {
// add wrapping sheet row to print model
printModel.addRow((WrappingSheets) table.getValueAt(i, -1));
} else {
// if not the same, i.e., value changed
// create a new table
JTable toPrint = new JTable(printModel);
// set size of table as if size isn't set the table contents aren't printed
toPrint.setSize(toPrint.getPreferredSize());
// reduce row height for printing
toPrint.setRowHeight(16);
// add table to print to list of tables to be printed
tablesToPrint.add(toPrint);
// create a new print model for next table to be printed
printModel = new WrappingSheetsTableModel();
// add first new wrapping sheet row to print model
printModel.addRow((WrappingSheets) table.getValueAt(i, -1));
// increment the wrapping line number
wrappingLineNumber = (Integer) table.getValueAt(i, 0);
}
}
// add in last table to print
JTable toPrint = new JTable(printModel);
// set size of table as if size isn't set the table contents aren't printed
toPrint.setSize(toPrint.getPreferredSize());
// reduce row height for printing
toPrint.setRowHeight(16);
// add last table to print to list of tables to be printed
tablesToPrint.add(toPrint);
// add each table to be printed to book for printing
int totalPages = 0;
for (JTable table : tablesToPrint) {
// get the table header information from table
JTableHeader tableHeader = table.getTableHeader();
// set size so that table header will be visible
tableHeader.setSize(tableHeader.getPreferredSize());
// get number of pages in printable table
int pages = getNumberOfPages(table.getPrintable(PrintMode.FIT_WIDTH, null, null), pf);
// create temporary printable to add to book
Printable p = table.getPrintable(PrintMode.FIT_WIDTH, null, null);
// add printable to book using printable wrapper
// p - printable, totalPages - total pages, pf - page format, pages - num pages to add
bookToPrint.append(new PrintableWrapper(p, totalPages), pf, pages);
// increase total pages count
totalPages += pages;
}
//Checks for page count:
//System.out.println(totalPages);
//System.out.println(bookToPrint.getNumberOfPages());
// Queries document for the number of pages
// and the PageFormat
// and Printable
// for each page held in the Pageable instance, document.
printerJob.setPageable(bookToPrint);
// show print dialog
// - printer selection and pages to print work
// - changing from e.g. landscape to portrait does not work currently
if(printerJob.printDialog()) printerJob.print();
System.out.println("success printing X");
} catch (PrinterException pe) {
System.out.println("printing failed");
pe.printStackTrace();
}
};
});
每个页面现在只包含那些具有相同换行号的行,并且当换行号改变时开始新的页面。 (仍然需要对 PageFormat 和 PrintDialog 进行更多研究,因为打印对话框中页面方向的更改目前不会影响最终的打印布局)。
我正在尝试找到一种以编程方式设置分页符以打印出 JTable 的方法。
例如,我有一个 table 大约有 150 行,如下所示:
行号Data1 Data2 Data3 …等
1 a b c d
1 a b c d
1 a b c d
2 a b c d
2 a b c d
3 a b c d
3 a b c d
3 a b c d
3 a b c d
4 a b c d
5 a b c d
5 a b c d
5 a b c d
…等 …等…等…等…等
我需要想办法在行号改变时开始打印新的一页。
我找到了 printing selected rows 的方法,到目前为止已经修改它以循环遍历我的 table 将行添加到临时打印模型,然后在重置之前调用 print() 方法进行打印临时变量。但是,这意味着我可能调用 print() 10 次,每个行号调用一次,这是一个 unacceptable 解决方案。完成当前漏洞解决方案的代码如下:
btnPrint.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent arg0) {
try {
int wrappingLineNumber = (Integer) table.getValueAt(0, 0);
WrappingSheetsTableModel printModel = new WrappingSheetsTableModel();
for (int i = 0; i < table.getRowCount(); i++) {
if ((Integer)table.getValueAt(i, 0) == wrappingLineNumber) {
System.out.println(table.getValueAt(i, -1));
printModel.addRow((WrappingSheets) table.getValueAt(i, -1));
} else {
wrappingLineNumber = (Integer) table.getValueAt(i, 0);
// if not the same, i.e., value changed
JTable toPrint = new JTable(printModel);
toPrint.setSize(toPrint.getPreferredSize());
JTableHeader tableHeader = toPrint.getTableHeader();
tableHeader.setSize(tableHeader.getPreferredSize());
toPrint.print(JTable.PrintMode.FIT_WIDTH);
printModel.removeAll();
printModel.addRow((WrappingSheets) table.getValueAt(i, -1));
}
}
System.out.println("success printing");
} catch (PrinterException pe) {
System.out.println("printing failed");
pe.printStackTrace();
}
};
});
任何人都可以提供更好的解决方案,只要行号列中的值发生变化,就会在新页面上开始打印吗?
非常感谢您提供的任何帮助!
经过进一步的研究和思考,我意识到可以创建 sub-tables/temporary tables 只保存与每条换行相关的信息。接下来的问题是如何将多个 JTable 作为一个打印作业进行打印。已提出并回答了此问题的变体 here and particularly here。根据第二个 link 中提供的信息,我想出的解决方案如下:
解决方案使用 Durandal 在上面的 link 2 中提供的未更改的 PrintableWrapper,包含在此处仅供参考 "to spare us the hassle of iterating over each page":
public class PrintableWrapper implements Printable {
private Printable delegate;
private int offset;
public PrintableWrapper(Printable delegate, int offset) {
this.offset = offset;
this.delegate = delegate;
}
@Override
public int print(Graphics graphics, PageFormat pageFormat, int pageIndex) throws PrinterException {
return delegate.print(graphics, pageFormat, pageIndex-offset);
}}
解决方案还利用相同 link 中未更改的 kleopatra / Durandal 代码来获取每个 table 所需的页数:
public int getNumberOfPages(Printable delegate, PageFormat pageFormat) throws PrinterException {
Graphics g = new BufferedImage(1, 1, BufferedImage.TYPE_INT_RGB).createGraphics();
int numPages = 0;
while (true) {
int result = delegate.print(g, pageFormat, numPages);
if (result == Printable.PAGE_EXISTS) {
++numPages;
} else {
break;
}
}
return numPages;
}
据此,解决方案是创建 PrinterJob、Book 和临时 JTable。然后把临时的table加到书里,用上面的class和方法。最后打印这本书。此解决方案的当前代码可以在下面找到,代码中包含解释性注释:
btnPrint.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent arg0) {
try {
//Code revised from
// \/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/
PrinterJob printerJob = PrinterJob.getPrinterJob();
//Set 1/4 " margins and orientation
PageFormat pf = printerJob.defaultPage();
pf.setOrientation(PageFormat.LANDSCAPE);
Paper paper = new Paper();
//double margin = 36; // half inch
double margin = 18; // quarter inch
paper.setImageableArea(margin, margin, paper.getWidth() - margin * 2, paper.getHeight() - margin * 2);
pf.setPaper(paper);
Book bookToPrint = new Book();
// /\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\
//Code revised from
// List to store temporary tables to print
List<JTable> tablesToPrint = new ArrayList<JTable>();
// create temporary print tables by wrapping line number
int wrappingLineNumber = (Integer) table.getValueAt(0, 0);
WrappingSheetsTableModel printModel = new WrappingSheetsTableModel();
for (int i = 0; i < table.getRowCount(); i++) {
if ((Integer)table.getValueAt(i, 0) == wrappingLineNumber) {
// add wrapping sheet row to print model
printModel.addRow((WrappingSheets) table.getValueAt(i, -1));
} else {
// if not the same, i.e., value changed
// create a new table
JTable toPrint = new JTable(printModel);
// set size of table as if size isn't set the table contents aren't printed
toPrint.setSize(toPrint.getPreferredSize());
// reduce row height for printing
toPrint.setRowHeight(16);
// add table to print to list of tables to be printed
tablesToPrint.add(toPrint);
// create a new print model for next table to be printed
printModel = new WrappingSheetsTableModel();
// add first new wrapping sheet row to print model
printModel.addRow((WrappingSheets) table.getValueAt(i, -1));
// increment the wrapping line number
wrappingLineNumber = (Integer) table.getValueAt(i, 0);
}
}
// add in last table to print
JTable toPrint = new JTable(printModel);
// set size of table as if size isn't set the table contents aren't printed
toPrint.setSize(toPrint.getPreferredSize());
// reduce row height for printing
toPrint.setRowHeight(16);
// add last table to print to list of tables to be printed
tablesToPrint.add(toPrint);
// add each table to be printed to book for printing
int totalPages = 0;
for (JTable table : tablesToPrint) {
// get the table header information from table
JTableHeader tableHeader = table.getTableHeader();
// set size so that table header will be visible
tableHeader.setSize(tableHeader.getPreferredSize());
// get number of pages in printable table
int pages = getNumberOfPages(table.getPrintable(PrintMode.FIT_WIDTH, null, null), pf);
// create temporary printable to add to book
Printable p = table.getPrintable(PrintMode.FIT_WIDTH, null, null);
// add printable to book using printable wrapper
// p - printable, totalPages - total pages, pf - page format, pages - num pages to add
bookToPrint.append(new PrintableWrapper(p, totalPages), pf, pages);
// increase total pages count
totalPages += pages;
}
//Checks for page count:
//System.out.println(totalPages);
//System.out.println(bookToPrint.getNumberOfPages());
// Queries document for the number of pages
// and the PageFormat
// and Printable
// for each page held in the Pageable instance, document.
printerJob.setPageable(bookToPrint);
// show print dialog
// - printer selection and pages to print work
// - changing from e.g. landscape to portrait does not work currently
if(printerJob.printDialog()) printerJob.print();
System.out.println("success printing X");
} catch (PrinterException pe) {
System.out.println("printing failed");
pe.printStackTrace();
}
};
});
每个页面现在只包含那些具有相同换行号的行,并且当换行号改变时开始新的页面。 (仍然需要对 PageFormat 和 PrintDialog 进行更多研究,因为打印对话框中页面方向的更改目前不会影响最终的打印布局)。