Как все уже упоминали (пока я отдыхал в отпуске :-) - TablePrintable тесно связан для секретности, нет возможности создавать подклассы, нет способа настроить печать верхнего / нижнего колонтитула. Единственный вариант перехвата - обернуть таблицу для печати по умолчанию, позволить ей выполнять свою работу без верхнего / нижнего колонтитула и взять на себя печать верхнего / нижнего колонтитула самостоятельно.
Проблема с фрагментами, показанными до сих пор, состоит в том, что они не очень хорошо работают с многостраничными страницами - как это известно и упоминалось всеми авторами, конечно, - потому что печатная форма по умолчанию считает, что нет верхних и нижних колонтитулов и свободно использует требуемое пространство ими. Не удивительно: -)
Так что вопрос: есть ли способ сделать так, чтобы по умолчанию не печатать в области верхнего / нижнего колонтитула? И да, это так: ответ двойного обхвата (эээ… обертка) - заставьте печатную машину по умолчанию считать, что у нее меньше места для печати, оборачивая данный pageFormat в тот, который возвращает скорректированный getImageableHeight / Y. Что-то вроде:
public class CustomPageFormat extends PageFormat {
private PageFormat delegate;
private double headerHeight;
private double footerHeight;
public CustomPageFormat(PageFormat format, double headerHeight, double footerHeight) {
this.delegate = format;
this.headerHeight = headerHeight;
this.footerHeight = footerHeight;
}
/**
* @inherited <p>
*/
@Override
public double getImageableY() {
return delegate.getImageableY() + headerHeight;
}
/**
* @inherited <p>
*/
@Override
public double getImageableHeight() {
return delegate.getImageableHeight() - headerHeight - footerHeight;
}
// all other methods simply delegate
Затем используйте в оболочке для печати (нижний колонтитул должен быть выполнен аналогично):
public class CustomTablePrintable implements Printable {
Printable tablePrintable;
JTable table;
MessageFormat header;
MessageFormat footer;
public CustomTablePrintable(MessageFormat header, MessageFormat footer) {
this.header = header;
this.footer = footer;
}
public void setTablePrintable(JTable table, Printable printable) {
tablePrintable = printable;
this.table = table;
}
@Override
public int print(Graphics graphics, PageFormat pageFormat,
int pageIndex) throws PrinterException {
// grab an untainted graphics
Graphics2D g2d = (Graphics2D)graphics.create();
// calculate the offsets and wrap the pageFormat
double headerOffset = calculateHeaderHeight(g2d, pageIndex);
CustomPageFormat wrappingPageFormat = new CustomPageFormat(pageFormat, headerOffset, 0);
// feed the wrapped pageFormat into the default printable
int exists = tablePrintable.print(graphics, wrappingPageFormat, pageIndex);
if (exists != PAGE_EXISTS) {
g2d.dispose();
return exists;
}
// translate the graphics to the start of the original pageFormat and draw header
g2d.translate(pageFormat.getImageableX(), pageFormat.getImageableY());
printHeader(g2d, pageIndex, (int) pageFormat.getImageableWidth());
g2d.dispose();
return PAGE_EXISTS;
}
protected double calculateHeaderHeight(Graphics2D g, int pageIndex) {
if (header == null) return 0;
Object[] pageNumber = new Object[]{new Integer(pageIndex + 1)};
String text = header.format(pageNumber);
Font headerFont = table.getFont().deriveFont(Font.BOLD, 18f);
g.setFont(headerFont);
Rectangle2D rect = g.getFontMetrics().getStringBounds(text, g);
return rect.getHeight();
}
protected void printHeader(Graphics2D g, int pageIndex, int imgWidth) {
Object[] pageNumber = new Object[]{new Integer(pageIndex + 1)};
String text = header.format(pageNumber);
Font headerFont = table.getFont().deriveFont(Font.BOLD, 18f);
g.setFont(headerFont);
Rectangle2D rect = g.getFontMetrics().getStringBounds(text, g);
// following is c&p from TablePrintable printText
int tx;
// if the text is small enough to fit, center it
if (rect.getWidth() < imgWidth) {
tx = (int) ((imgWidth - rect.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()));
g.setColor(Color.BLACK);
g.drawString(text, tx, ty);
}
}
И в конце вернуть это из таблицы getPrintable, например:
final JTable table = new JTable(myModel){
/**
* @inherited <p>
*/
@Override
public Printable getPrintable(PrintMode printMode,
MessageFormat headerFormat, MessageFormat footerFormat) {
Printable printable = super.getPrintable(printMode, null, null);
CustomTablePrintable custom = new CustomTablePrintable(headerFormat, footerFormat);
custom.setTablePrintable(this, printable);
return custom;
}
};
printHeader / Footer может быть реализован, чтобы делать все, что требуется.
В конце дня: ответ на вопрос «нужно ли мне вызывать g.drawString (...)» по-прежнему «Да». Но, по крайней мере, это безопасно за пределами самой таблицы: -)