表打印不适合页面大小 [英] Table Print does not fit to page size

查看:191
本文介绍了表打印不适合页面大小的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

所以,我有一个打印按钮,打印我的jTable2使用自定义打印功能。我还使用调整大小功能,调整列的大小打印。但是,我试图使表适合页面的宽度,但它不这样做,即使我将PrintMode更改为FIT_WIDTH或NORMAL,它们之间没有区别。此外,我已经尝试更改表的字体大小,但它没有工作。这里是代码:

  package sistemabt; 

import java.sql。*;

import java.util.Vector;

import javax.swing.JApplet;

import javax.swing.JOptionPane;

import javax.swing.table.DefaultTableModel;

import java.awt。*;

import java.awt.event。*;

import java.text。*;

import java.awt.print。*;

import javax.swing.JTable;

import javax.swing.table.TableColumn。*;

import javax.swing.table.JTableHeader;

import javax.swing.table.TableColumnModel;

import java.awt.geom.Rectangle2D;

import java.awt.geom.AffineTransform;

import java.awt.BorderLayout;

import java.awt.EventQueue;

import java.awt.event.ActionEvent;

import java.awt.event.ActionListener;

import java.awt.print.PrinterException;

import java.util.Vector;

import java.util.logging.Level;

import java.util.logging.Logger;

import javax.swing.JButton;

import javax.swing.JFrame;

import javax.swing.JScrollPane;

import javax.swing.JTable;

import javax.swing.UIManager;

import javax.swing.UnsupportedLookAndFeelException;

import javax.swing.table.DefaultTableModel;

import javax.swing.table.JTableHeader;

import javax.swing.table.DefaultTableCellRenderer;

import javax.swing.table.JTableHeader;

import javax.swing.table.TableCellRenderer;

import javax.swing.table.TableColumn;

import java.awt.Component;

import java.awt.FontMetrics;

public class FormNotas extends javax.swing.JFrame {

private String driver =org.postgresql.Driver;
private String banco =bancoBT;
private String host =localhost;
private String str_conn =jdbc:postgresql:// localhost:5432 /+ banco;
private String usuario =postgres;
private String senha =root;

public static Connection con;
private Statement stmt;
private ResultSet rs;
public String sql;
public PreparedStatement pst;

静态类TablePrintable实现Printable {

private final JTable表;
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 = 15.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){
//头文件夹高度可以设置一次,因为它不变
hclip.height = header.getHeight();
}

this.printMode = printMode;

this.headerFormat = headerFormat;
this.footerFormat = footerFormat;

//从表的字体中导出页眉和页脚字体
headerFont = table.getFont()。derivedFont(Font.BOLD,HEADER_FONT_SIZE);
footerFont = table.getFont()。derivFont(Font.PLAIN,FOOTER_FONT_SIZE);
}

@Override
public int print(Graphics Graphics,PageFormat pageFormat,int pageIndex)throws PrinterException {

//以便于访问values
final int imgWidth =(int)pageFormat.getImageableWidth();
final int imgHeight =(int)pageFormat.getImageableHeight();

if(imgWidth< = 0){
throw new PrinterException(可打印区域的宽度太小。
}

//格式化页眉和页脚时传递页码
// text
Object [] pageNumber = new Object [] {Integer.valueOf (pageIndex + 1)};

//获取格式化的标题文本(如果有)
String headerText = null;
if(headerFormat!= null){
headerText = headerFormat.format(pageNumber);
}

//获取格式化的页脚文本(如果有)
String footerText = null;
if(footerFormat!= null){
footerText = footerFormat.format(pageNumber);
}

//存储页眉和页脚文本的边界
Rectangle2D hRect = null;
Rectangle2D fRect = null;

//页眉和页脚所需的垂直空间量
// text
int headerTextSpace = 0;
int footerTextSpace = 0;

//可用于打印表的垂直空间量
int availableSpace = imgHeight;

//如果有头文本,找出需要多少空间
//并从可用空间中减去
if(headerText!= null){
graphics.setFont(headerFont);
int nbLines = headerText.split(\\\
)。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(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(可打印区域的高度太小。
}

//根据打印模式,我们可能需要一个比例因子到
//在表的整个宽度上适合页面
double sf = 1.0 D;
if(printMode == JTable.PrintMode.FIT_WIDTH&& totalColWidth> imgWidth){

//如果不是,我们以前会抛出一个接受
assert imgWidth > 0;

//必须是,根据if条件,因为imgWidth> 0
assert totalColWidth> 1;

sf =(double)imgWidth /(double)totalColWidth;
}

//由前两个断言决定
assert sf> 0;

//这是一个循环,有两个原因:
//首先,它允许我们赶上,如果我们叫起始
//,零pageIndex。第二,我们知道我们可以称为
//同一页多次。这种情况下
//循环作为一个检查,确保我们不再尝试做
//计算,当我们为
//调用后续时间时页。
while(last< pageIndex){
//如果我们完成所有行中的所有列
if(row> = table.getRowCount()&& col == 0 ){
return NO_SUCH_PAGE;
}

//而不是在findNextClip中将每行和列乘以标度
// factor
//,只需传递一个宽度和高度,即
//已经
//除以
int scaledWidth =(int)(imgWidth / sf);
int scaledHeight =(int)((availableSpace - hclip.height)/ sf);

//计算要为此页面打印的表的区域
findNextClip(scaledWidth,scaledHeight);

last ++;
}

//创建一个图形的副本,所以我们不影响
// us
Graphics2D g2d =(Graphics2D)图形的副本。创建();

//翻译成pageFormat的坐标系统
g2d.translate(pageFormat.getImageableX(),pageFormat.getImageableY());

//保存和存储转换
AffineTransform oldTrans;

//如果有页脚文本,请在可映像的底部打印
//区域
if(footerText!= null){
oldTrans = g2d。 getTransform();

g2d.translate(0,imgHeight - footerTextSpace);

String [] lines = footerText.split(\\\
);
printText(g2d,lines,fRect,footerFont,imgWidth);

g2d.setTransform(oldTrans);
}

//如果有标题文本,请在可成像区域的顶部打印
//然后向下平移
if(headerText!= null) {
String [] lines = headerText.split(\\\
);
printText(g2d,lines,hRect,headerFont,imgWidth);

g2d.translate(0,headerTextSpace + H_F_SPACE);
}

//将表输出限制到可用空间
tempRect.x = 0;
tempRect.y = 0;
tempRect.width = imgWidth;
tempRect.height = availableSpace;
g2d.clip(tempRect);

//如果我们有一个比例因子,缩放图形对象以适应
//整个宽度
if(sf!= 1.0D){
g2d .scale(sf,sf);

//否则,确保表的当前部分是
//水平居中
} else {
int diff =(imgWidth - clip.width) / 2;
g2d.translate(diff,0);
}

//存储旧的转换和剪辑以供以后恢复
oldTrans = g2d.getTransform();
Shape oldClip = g2d.getClip();

//如果有一个表头,打印当前节和
//然后向下翻译
if(header!= null){
hclip.x = clip.x;
hclip.width = clip.width;

g2d.translate(-hclip.x,0);
g2d.clip(hclip)
header.print(g2d);

//恢复原始变换和剪辑
g2d.setTransform(oldTrans);
g2d.setClip(oldClip);

//向下翻译
g2d.translate(0,hclip.height);
}

//打印表的当前部分
g2d.translate(-clip.x,-clip.y);
g2d.clip(clip);
table.print(g2d);

//恢复原始变换和剪辑
g2d.setTransform(oldTrans);
g2d.setClip(oldClip);

//在表周围绘制一个框
g2d.setColor(Color.BLACK);
g2d.drawRect(0,0,clip.width,hclip.height + clip.height);

//处理图形副本
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(rect.getWidth()< imgWidth){
tx =(int)(imgWidth / 2 - g2d.getFontMetrics()。getStringBounds(lines [i],g2d).getWidth()/ 2);

//否则,如果表是LTR,确保
//的左侧文本显示;右边可以剪辑
} else if(table.getComponentOrientation()。isLeftToRight()){
tx = 0;

//否则,确保文本的右边显示
} 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(col == 0){
if(ltr){
// adjust剪辑到第一列的左边
clip.x = 0;
} else {
//调整第一列右边的剪辑
clip.x = totalColWidth;
}

//将剪辑调整到下一行的顶部
clip.y + = clip.height;

//将剪辑宽度和高度调整为零
clip.width = 0;
clip.height = 0;

//适合尽可能多的行,并且至少有一个
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);
}

//从
开始我们可以短路JTable.PrintMode.FIT_WIDTH //我们总是适合页面上的所有列
if(printMode == JTable.PrintMode.FIT_WIDTH){
clip.x = 0;
clip.width = totalColWidth;
return;
}

if(ltr){
//调整剪辑到下一组列的左边
clip.x + = clip.width;
}

//将剪辑宽度调整为零
clip.width = 0;

//适合尽可能多的列,并且至少有一个
int colCount = table.getColumnCount();
int colWidth = colModel.getColumn(col).getWidth();
do {
clip.width + = colWidth;
if(!ltr){
clip.x - = colWidth;
}

if(++ col> = colCount){
//将col重置为0表示我们完成了所有列
col = 0;

break;
}

colWidth = colModel.getColumn(col).getWidth();
} while(clip.width + colWidth< = pw);
}
}

static class ColumnsAutoSizer {

public static void sizeColumnsToFit(JTable table){
sizeColumnsToFit(table,3);
}

public static void sizeColumnsToFit(JTable table,int columnMargin){
JTableHeader tableHeader = table.getTableHeader();

if(tableHeader == null){
//不能自动调整没有标题的表
return;
}

FontMetrics headerFontMetrics = tableHeader.getFontMetrics(tableHeader.getFont());

int [] minWidths = new int [table.getColumnCount()];
int [] maxWidths = new int [table.getColumnCount()];

for(int columnIndex = 0; columnIndex< table.getColumnCount(); columnIndex ++){
int headerWidth = headerFontMetrics.stringWidth(table.getColumnName(columnIndex));

minWidths [columnIndex] = headerWidth + columnMargin;

int maxWidth = getMaximalRequiredColumnWidth(table,columnIndex,headerWidth);

maxWidths [columnIndex] = Math.max(maxWidth,minWidths [columnIndex])+ columnMargin;
}

adjustMaximumWidths(table,minWidths,maxWidths);

for(int i = 0; i if(minWidths [i]> 0){
table.getColumnModel()。 getColumn(i).setMinWidth(minWidths [i]);
}

if(maxWidths [i]> 0){
table.getColumnModel()。getColumn(i).setMaxWidth(maxWidths [i]);

table.getColumnModel()。getColumn(i).setWidth(maxWidths [i]);
}
}
}

private static void adjustMaximumWidths(JTable table,int [] minWidths,int [] maxWidths){
if(table。 getWidth()> 0){
//在异常情况下防止无限循环
int breaker = 0;

//保持窃取最高列最大宽度的一个像素,直到我们可以适应表的宽度
while(sum(maxWidths)> table.getWidth()& ;& breaker< 10000){
int highestWidthIndex = findLargestIndex(maxWidths);

maxWidths [highestWidthIndex] - = 1;

maxWidths [highestWidthIndex] = Math.max(maxWidths [highestWidthIndex],minWidths [highestWidthIndex]);

breaker ++;
}
}
}

private static int getMaximalRequiredColumnWidth(JTable table,int columnIndex,int headerWidth){
int maxWidth = headerWidth;

TableColumn column = table.getColumnModel()。getColumn(columnIndex);

TableCellRenderer cellRenderer = column.getCellRenderer();

if(cellRenderer == null){
cellRenderer = new DefaultTableCellRenderer();
}

for(int row = 0; row< table.getModel()。getRowCount(); row ++){
Component rendererComponent = cellRenderer.getTableCellRendererComponent(table,
table.getModel()。getValueAt(row,columnIndex),
false,
false,
row,
columnIndex);

double valueWidth = rendererComponent.getPreferredSize()。getWidth();

maxWidth =(int)Math.max(maxWidth,valueWidth);
}

return maxWidth;
}

private static int findLargestIndex(int [] width){
int largestIndex = 0;
int highestValue = 0;

for(int i = 0; i< widths.length; i ++){
if(width [i]> highestValue){
largestIndex =
highestValue = width [i];
}
}

return maximumIndex;
}

private static int sum(int [] width){
int sum = 0;

for(int width:wides){
sum + = width;
}

return sum;
}

}

/ **
*创建新表单FormNotas
* /
public FormNotas(){
initComponents();
try {
try {
Class.forName(driver);
} catch(ClassNotFoundException ex){
ex.printStackTrace();
}

con = DriverManager.getConnection(str_conn,usuario,senha);
stmt = con.createStatement();

sql =select Nome_Curso from curso order by Nome_Curso;
rs = stmt.executeQuery(sql);

while(rs.next()){
jComboBox1.addItem(rs.getString(Nome_Curso));
}

} catch(SQLException ex){
JOptionPane.showMessageDialog(null,Ocorreu um erro ao carregar o ComboBox);
System.out.println(Ocorreu um erro ao carregar o ComboBox);
}

try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch(ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex){
ex.printStackTrace();
}

DefaultTableModel model = new DefaultTableModel(0,26);
for(int row = 0; row< 26; row ++){
Vector data = new Vector(26);
for(int col = 0; col< 26; col ++){

String value = row +x+((char)(col +'A'))
data.add(value);

}
model.addRow(data);
}
JTable jTable2 = new JTable(model);
}


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 vetColuna.add(rsmd.getColumnLabel(i + 1));
}

while(rs.next()){
Vector vetLinha = new Vector();
for(int i = 0; i vetLinha.add(rs.getObject(i + 1));
}
vetLinhas.add(vetLinha);
}
} catch(ClassNotFoundException ex){
JOptionPane.showMessageDialog(null,Erro\NNãofoipossívelcarregar 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 \\\
campos estejam preenchidos corretamente。
System.out.println(Problema com o SQL);
ex.printStackTrace();
}

MessageFormat header = new MessageFormat(FichaPedagógica - + jComboBox1.getSelectedItem()+\\\
Nome do Aluno - + jTextField1.getText());

jTable2.setModel(new DefaultTableModel(vetLinhas,vetColuna));
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);
}
};

ColumnsAutoSizer.sizeColumnsToFit(jTable2);
try {
jTable2.setSize(jTable2.getPreferredSize());
JTableHeader tableHeader = jTable2.getTableHeader();
tableHeader.setSize(tableHeader.getPreferredSize());
jTable2.print(JTable.PrintMode.FIT_WIDTH,header,null);
} catch(PrinterException ex){
ex.printStackTrace();
}

}

页面正在查看此时: http://i.imgur.com/29gHNnj.png



我想说的是,该表在页面上非常小,我想调整它的大小以适应页面宽度,并且字体更大。

解决方案

有两种可能的选项,您可以尝试调整列大小,



缩放



默认情况下, TablePrintable 只能向下缩放,迫使 JTable 太大,不适合可用的页面大小(宽度)。



计算比例的代码片段在 print c。 $ 类。

  double sf = 1.0D; 
if(printMode == JTable.PrintMode.FIT_WIDTH&& totalColWidth> imgWidth){

//如果不是,我们以前会抛出一个接受
assert imgWidth > 0;

//必须是,根据if条件,因为imgWidth> 0
assert totalColWidth> 1;

sf =(double)imgWidth /(double)totalColWidth;
}

我们感兴趣的部分是 if 语句,其中显示if printmode equals FIT_WIDTH AND the totalColWidth is greater the the page width...如果printmode等于FIT_WIDTH,则我们希望将其改为read ...



您可以更改

  if(printMode == JTable.PrintMode.FIT_WIDTH& ;& totalColWidth> imgWidth){


$ b b

  if(printMode == JTable.PrintMode.FIT_WIDTH){


$ b b

现在允许 TablePrintable 同时缩放表UP和DOWN ...








  • 顶部是屏幕输出

  • 左为当前结果

  • 右键是缩放结果



调整列大小



是一个有点更棘手,不应该应用于已经在屏幕上的 JTable ,因为这将会弄乱它是如何实际显示...



基本上,当打印表时,我们将覆盖列宽,使页面间的空间相等...



首先,我们需要在 TablePrintable 中更改 totalColWidth b

  private final int totalColWidth; 

  private int totalColWidth; 

,因为我们需要在初始化后修改值...



接下来,我们需要一个标志来确定列是否已被修改,因为每次 print 的字段添加 private boolean updateColumnWidths; TablePrintable (例如, private final Font footerFont;



print 被调用,我们需要做一系列的决定...

  public int print(Graphics Graphics,PageFormat pageFormat,int pageIndex)throws PrinterException {

//以方便访问这些值
final int imgWidth =(int)pageFormat.getImageableWidth ;
final int imgHeight =(int)pageFormat.getImageableHeight();

if(imgWidth< = 0){
throw new PrinterException(可打印区域的宽度太小。
}

//我们修改了列宽吗?
if(!updateColumnWidths){

//如果当前总列宽度
//小于可用的imgWidth(页面宽度),则只更新列宽
if(totalColWidth< imgWidth){

//计算所需的列宽以允许列
//跨页...
int columnCount = table。 getColumnCount();
int columnWidth =(int)(imgWidth /(float)columnCount);
TableColumnModel columnModel = table.getColumnModel();
//更新列...
for(int col = 0; col< columnModel.getColumnCount(); col ++){
TableColumn tc = columnModel.getColumn(col);
tc.setMinWidth(columnWidth);
tc.setMaxWidth(columnWidth);
tc.setPreferredWidth(columnWidth);
tc.setWidth(columnWidth);
}
//更新totalColWidth,这应该防止
//应用任何缩放
totalColWidth = columnModel.getTotalColumnWidth();

}
updateColumnWidths = true;

}
// ...

喜欢...




So, I have a "print" button, that prints my jTable2 using a custom "print" function. I also use a "resize" function, to resize the columns for printing. But, I've tried to make the table fit the width of the page, but it doesn't do this, even if I change the PrintMode to FIT_WIDTH, or NORMAL, it has no difference between them. Also, I've tried changing the font size of the table, but it didn't work too. Here is the code:

package sistemabt;

import java.sql.*;

import java.util.Vector;

import javax.swing.JApplet;

import javax.swing.JOptionPane;

import javax.swing.table.DefaultTableModel;

import java.awt.*;

import java.awt.event.*;

import java.text.*;

import java.awt.print.*;

import javax.swing.JTable;

import javax.swing.table.TableColumn.*;

import javax.swing.table.JTableHeader;

import javax.swing.table.TableColumnModel;

import java.awt.geom.Rectangle2D;

import java.awt.geom.AffineTransform;

import java.awt.BorderLayout;

import java.awt.EventQueue;

import java.awt.event.ActionEvent;

import java.awt.event.ActionListener;

import java.awt.print.PrinterException;

import java.util.Vector;

import java.util.logging.Level;

import java.util.logging.Logger;

import javax.swing.JButton;

import javax.swing.JFrame;

import javax.swing.JScrollPane;

import javax.swing.JTable;

import javax.swing.UIManager;

import javax.swing.UnsupportedLookAndFeelException;

import javax.swing.table.DefaultTableModel;

import javax.swing.table.JTableHeader;

import javax.swing.table.DefaultTableCellRenderer;

import javax.swing.table.JTableHeader;

import javax.swing.table.TableCellRenderer;

import javax.swing.table.TableColumn;

import java.awt.Component;

import java.awt.FontMetrics;

public class FormNotas extends javax.swing.JFrame {

private String driver = "org.postgresql.Driver";
private String banco = "bancoBT";
private String host = "localhost";
private String str_conn = "jdbc:postgresql://localhost:5432/" + banco;
private String usuario = "postgres";
private String senha = "root";

public static Connection con;
private Statement stmt;
private ResultSet rs;
public String sql;
public PreparedStatement pst;

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 = 15.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);
    }
}

static class ColumnsAutoSizer {

    public static void sizeColumnsToFit(JTable table) {
        sizeColumnsToFit(table, 3);
    }

    public static void sizeColumnsToFit(JTable table, int columnMargin) {
        JTableHeader tableHeader = table.getTableHeader();

        if (tableHeader == null) {
            // can't auto size a table without a header
            return;
        }

        FontMetrics headerFontMetrics = tableHeader.getFontMetrics(tableHeader.getFont());

        int[] minWidths = new int[table.getColumnCount()];
        int[] maxWidths = new int[table.getColumnCount()];

        for (int columnIndex = 0; columnIndex < table.getColumnCount(); columnIndex++) {
            int headerWidth = headerFontMetrics.stringWidth(table.getColumnName(columnIndex));

            minWidths[columnIndex] = headerWidth + columnMargin;

            int maxWidth = getMaximalRequiredColumnWidth(table, columnIndex, headerWidth);

            maxWidths[columnIndex] = Math.max(maxWidth, minWidths[columnIndex]) + columnMargin;
        }

        adjustMaximumWidths(table, minWidths, maxWidths);

        for (int i = 0; i < minWidths.length; i++) {
            if (minWidths[i] > 0) {
                table.getColumnModel().getColumn(i).setMinWidth(minWidths[i]);
            }

            if (maxWidths[i] > 0) {
                table.getColumnModel().getColumn(i).setMaxWidth(maxWidths[i]);

                table.getColumnModel().getColumn(i).setWidth(maxWidths[i]);
            }
        }
    }

    private static void adjustMaximumWidths(JTable table, int[] minWidths, int[] maxWidths) {
        if (table.getWidth() > 0) {
            // to prevent infinite loops in exceptional situations
            int breaker = 0;

            // keep stealing one pixel of the maximum width of the highest column until we can fit in the width of the table
            while (sum(maxWidths) > table.getWidth() && breaker < 10000) {
                int highestWidthIndex = findLargestIndex(maxWidths);

                maxWidths[highestWidthIndex] -= 1;

                maxWidths[highestWidthIndex] = Math.max(maxWidths[highestWidthIndex], minWidths[highestWidthIndex]);

                breaker++;
            }
        }
    }

    private static int getMaximalRequiredColumnWidth(JTable table, int columnIndex, int headerWidth) {
        int maxWidth = headerWidth;

        TableColumn column = table.getColumnModel().getColumn(columnIndex);

        TableCellRenderer cellRenderer = column.getCellRenderer();

        if (cellRenderer == null) {
            cellRenderer = new DefaultTableCellRenderer();
        }

        for (int row = 0; row < table.getModel().getRowCount(); row++) {
            Component rendererComponent = cellRenderer.getTableCellRendererComponent(table,
                    table.getModel().getValueAt(row, columnIndex),
                    false,
                    false,
                    row,
                    columnIndex);

            double valueWidth = rendererComponent.getPreferredSize().getWidth();

            maxWidth = (int) Math.max(maxWidth, valueWidth);
        }

        return maxWidth;
    }

    private static int findLargestIndex(int[] widths) {
        int largestIndex = 0;
        int largestValue = 0;

        for (int i = 0; i < widths.length; i++) {
            if (widths[i] > largestValue) {
                largestIndex = i;
                largestValue = widths[i];
            }
        }

        return largestIndex;
    }

    private static int sum(int[] widths) {
        int sum = 0;

        for (int width : widths) {
            sum += width;
        }

        return sum;
    }

}

/**
 * Creates new form FormNotas
 */
public FormNotas() {
    initComponents();
    try {
        try {
            Class.forName(driver);
        } catch (ClassNotFoundException ex) {
            ex.printStackTrace();
        }

        con = DriverManager.getConnection(str_conn, usuario, senha);
        stmt = con.createStatement();

        sql = "select Nome_Curso from curso order by Nome_Curso";
        rs = stmt.executeQuery(sql);

        while (rs.next()) {
            jComboBox1.addItem(rs.getString("Nome_Curso"));
        }

    } catch (SQLException ex) {
        JOptionPane.showMessageDialog(null, "Ocorreu um erro ao carregar o ComboBox");
        System.out.println("Ocorreu um erro ao carregar o ComboBox");
    }

    try {
        UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
    } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
        ex.printStackTrace();
    }

    DefaultTableModel model = new DefaultTableModel(0, 26);
    for (int row = 0; row < 26; row++) {
        Vector data = new Vector(26);
        for (int col = 0; col < 26; col++) {

            String value = row + "x" + ((char) (col + 'A'));
            data.add(value);

        }
        model.addRow(data);
    }
    JTable jTable2 = new JTable(model);
}


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());

    jTable2.setModel(new DefaultTableModel(vetLinhas, vetColuna));
    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);
        }
    };

    ColumnsAutoSizer.sizeColumnsToFit(jTable2);
    try {
        jTable2.setSize(jTable2.getPreferredSize());
        JTableHeader tableHeader = jTable2.getTableHeader();
        tableHeader.setSize(tableHeader.getPreferredSize());
        jTable2.print(JTable.PrintMode.FIT_WIDTH, header, null);
    } catch (PrinterException ex) {
        ex.printStackTrace();
    }

}    

And here's a image of how the page is looking at the moment: http://i.imgur.com/29gHNnj.png

What I'm trying to say is that the table is very small on the page, and I want it to be resized to fit the page width, and that the font can be bigger. How can I do that?

解决方案

There are two possible options you have, you could try and resize the columns so that are evenly distributed across the available page width OR you could scale the resulting output UP so it fits the page.

Scaling

By default, the TablePrintable only scales DOWN, forcing a JTable that is too large to fit within the available page size (width). You can change this to allow it to also scale UP.

The piece of code that calculates the scale is within the print of the TablePrintable class and looks like...

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;
}

The part we're interested in is the if statement, which reads "if printmode equals FIT_WIDTH AND the totalColWidth is greater the the page width"...We want to change this to read ""if printmode equals FIT_WIDTH" only...

You could change

if (printMode == JTable.PrintMode.FIT_WIDTH && totalColWidth > imgWidth) {

to

if (printMode == JTable.PrintMode.FIT_WIDTH) {

which will now allow the TablePrintable to both scale the table UP and DOWN...

Which will result in something like...

  • Top is the screen output
  • Left is the current result
  • Right is the scaled result

Resize Columns

This is a little more tricky and SHOULD never be applied to a JTable that is already on the screen, as this will mess with how it is actually displayed...

Basically, when the table is printed, we're going to override the column widths to give them equal space across the page...

First, we need to change totalColWidth in TablePrintable from...

private final int totalColWidth;

to

private int totalColWidth;

because we need to be able to modify the value after it's initialised...

Next, we need a flag to determine if the columns have been modified or not, as it's a waste to have to repeatedly update their sizes every time print is called.

Add private boolean updateColumnWidths; to the fields of TablePrintable (for example, under private final Font footerFont;)

Now, when print is called, we need to make a series of decisions...

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.");
    }

    // Have we modified the column widths yet??
    if (!updateColumnWidths) {

        // Only update the column widths if the current total column width
        // is less then the available imgWidth (page width)
        if (totalColWidth < imgWidth) {

            // Calculate the required column width to allow the columns to
            // span the page...
            int columnCount = table.getColumnCount();
            int columnWidth = (int) (imgWidth / (float) columnCount);
            TableColumnModel columnModel = table.getColumnModel();
            // Update the columns...
            for (int col = 0; col < columnModel.getColumnCount(); col++) {
                TableColumn tc = columnModel.getColumn(col);
                tc.setMinWidth(columnWidth);
                tc.setMaxWidth(columnWidth);
                tc.setPreferredWidth(columnWidth);
                tc.setWidth(columnWidth);
            }
            // Update the totalColWidth, this should prevent
            // any scaling been applied
            totalColWidth = columnModel.getTotalColumnWidth();

        }
        updateColumnWidths = true;

    }
    //...

Which generates something like...

这篇关于表打印不适合页面大小的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆