Java 截断的JTable打印输出

Java 截断的JTable打印输出,java,swing,printing,jtable,Java,Swing,Printing,Jtable,我有一个JTable,它使用JTextArea作为TableCellRenderer,因此表格单元格可以利用换行符。JTable显示良好。当我通过JTable将表格打印到打印机时,输出总是被截断在大约60%的数据上。我尝试过不同的计算机、不同的打印机、不同的打印机驱动程序、不同的JVM版本(1.5、1.6),但这些都没有用。下面是一个自包含的Java主类,它再现了这个问题。有什么想法吗 import java.awt.*; import java.awt.event.*; import java

我有一个JTable,它使用JTextArea作为TableCellRenderer,因此表格单元格可以利用换行符。JTable显示良好。当我通过JTable将表格打印到打印机时,输出总是被截断在大约60%的数据上。我尝试过不同的计算机、不同的打印机、不同的打印机驱动程序、不同的JVM版本(1.5、1.6),但这些都没有用。下面是一个自包含的Java主类,它再现了这个问题。有什么想法吗

import java.awt.*;
import java.awt.event.*;
import java.awt.print.*;
import java.util.*;
import javax.swing.*;
import javax.swing.table.*;

public class JTextAreaJTableTest extends javax.swing.JFrame {

    public static void main(String args[]) {
        java.awt.EventQueue.invokeLater(new Runnable() {
            public void run() {
                JTextAreaJTableTest frame = new JTextAreaJTableTest();
                frame.setSize(640, 480);
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
            }
        });
    }

    JButton jButtonPrint;
    JScrollPane jScrollPane;
    JTable jTable;
    JToolBar jToolBar;

    public JTextAreaJTableTest() {
        initComponents();

        DefaultTableModel dtm = (DefaultTableModel) jTable.getModel();
        Vector<Vector<String>> data = new Vector<Vector<String>>();
        for (int i = 0; i < 50; i++) {
            Vector<String> rowData = new Vector<String>();
            rowData.add("Entry " + i);
            rowData.add("Lorem ipsum dolor sit amet, consectetur adipisicing"
                    + " elit, sed do eiusmod tempor incididunt ut labore et"
                    + " dolore magna aliqua. Ut enim ad minim veniam, quis"
                    + " nostrud exercitation ullamco laboris nisi ut aliquip"
                    + " ex ea commodo consequat. Duis aute irure dolor in"
                    + " reprehenderit in voluptate velit esse cillum dolore"
                    + " eu fugiat nulla pariatur. Excepteur sint occaecat"
                    + " cupidatat non proident, sunt in culpa qui officia"
                    + " deserunt mollit anim id est laborum. " + i);
            data.add(rowData);
        }
        Vector<String> columnNames = new Vector<String>();
        columnNames.add("Key");
        columnNames.add("Value");
        dtm.setDataVector(data, columnNames);
        jTable.setDefaultRenderer(String.class, null);
        jTable.getColumnModel().getColumn(0).setCellRenderer(
                new TextAreaCellRenderer());
        jTable.getColumnModel().getColumn(1).setCellRenderer(
                new TextAreaCellRenderer());
    }

    private void initComponents() {
        jToolBar = new JToolBar();
        jButtonPrint = new JButton();
        jScrollPane = new JScrollPane();
        jTable = new JTable();

        setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);

        jToolBar.setRollover(true);

        jButtonPrint.setText("Print");
        jButtonPrint.setFocusable(false);
        jButtonPrint.setHorizontalTextPosition(SwingConstants.CENTER);
        jButtonPrint.setVerticalTextPosition(SwingConstants.BOTTOM);
        jButtonPrint.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent evt) {
                jButtonPrintActionPerformed(evt);
            }
        });
        jToolBar.add(jButtonPrint);

        getContentPane().add(jToolBar, BorderLayout.NORTH);

        jScrollPane.setViewportView(jTable);

        getContentPane().add(jScrollPane, BorderLayout.CENTER);
    }

    private void jButtonPrintActionPerformed(ActionEvent evt)                                             
    {                                                 
        try {
            jTable.print();
        } catch (PrinterException ex) {
            ex.printStackTrace();
        }
    }                                            

    public static class TextAreaCellRenderer extends JTextArea implements
            TableCellRenderer {

        public TextAreaCellRenderer() {
            this.setLineWrap(true);
            this.setWrapStyleWord(true);
        }

        public Component getTableCellRendererComponent(JTable table, 
                Object value, boolean isSelected, boolean hasFocus,
                int row, int column) {
            this.setText(String.valueOf(value));
            TableColumnModel columnModel = table.getColumnModel();
            this.setSize(columnModel.getColumn(column).getWidth(), 1);
            int newHeight = this.getPreferredSize().height;
            if (newHeight > table.getRowHeight(row)) {
                table.setRowHeight(row, this.getPreferredSize().height);
            }
            return this;
        }
    }
}
import java.awt.*;
导入java.awt.event.*;
导入java.awt.print.*;
导入java.util.*;
导入javax.swing.*;
导入javax.swing.table.*;
公共类JTextAreaJTableTest扩展了javax.swing.JFrame{
公共静态void main(字符串参数[]){
invokeLater(new Runnable()){
公开募捐{
JTextAreaJTableTest帧=新的JTextAreaJTableTest();
帧设置大小(640480);
frame.setLocationRelativeTo(空);
frame.setVisible(true);
}
});
}
JButton jButtonPrint;
JScrollPane JScrollPane;
JTable-JTable;
JToolBar JToolBar;
公共JTextAreaJTableTest(){
初始化组件();
DefaultTableModel dtm=(DefaultTableModel)jTable.getModel();
向量数据=新向量();
对于(int i=0;i<50;i++){
向量行数据=新向量();
行数据。添加(“条目”+i);
rowData.add(“Lorem ipsum dolor sit amet,Concertetur Adipising”
+“elit,我是临时雇员”
+“你的生活是多么美好”
+“nostrud实习ullamco laboris nisi ut aliquip”
+“前一个普通消费品,两人在一起”
+“用卷曲的丝绒和多洛尔的丝绒做修复”
+“欧盟无法定权利,圣奥凯卡除外”
+“不轻率,不必为官方过失”
+“这是我的劳动。”+i);
data.add(rowData);
}
向量列名称=新向量();
columnNames。添加(“键”);
列名称。添加(“值”);
setDataVector(数据、列名称);
setDefaultRenderer(String.class,null);
jTable.getColumnModel().getColumn(0).setCellRenderer(
新的TextAreaCellRenderer());
jTable.getColumnModel().getColumn(1).setCellRenderer(
新的TextAreaCellRenderer());
}
私有组件(){
jToolBar=新的jToolBar();
jButtonPrint=新JButton();
jScrollPane=新的jScrollPane();
jTable=新的jTable();
setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
jToolBar.setRollover(真);
jButtonPrint.setText(“打印”);
jButtonPrint.setFocusable(false);
jButtonPrint.setHorizontalTextPosition(SwingConstants.CENTER);
jButtonPrint.setVerticalTextPosition(SwingConstants.BOTTOM);
jButtonPrint.addActionListener(新ActionListener(){
已执行的公共无效操作(操作事件evt){
jButtonPrintActionPerformed(evt);
}
});
jToolBar.add(jButtonPrint);
getContentPane().add(jToolBar,BorderLayout.NORTH);
jScrollPane.setViewportView(jTable);
getContentPane().add(jScrollPane,BorderLayout.CENTER);
}
私有无效jButtonPrintActionPerformed(ActionEvent evt)
{                                                 
试一试{
jTable.print();
}捕获(打印例外){
例如printStackTrace();
}
}                                            
公共静态类TextAreaCellRenderer扩展了JTextArea实现
TableCell渲染器{
公共文本区域单元格渲染器(){
此参数为.setLineWrap(true);
此.setWrapStyleWord(true);
}
公共组件GetTableCellRenderComponent(JTable表,
对象值,布尔isSelected,布尔hasFocus,
整数行,整数列){
this.setText(String.valueOf(value));
TableColumnModel columnModel=table.getColumnModel();
这个.setSize(columnModel.getColumn(column.getWidth(),1);
int newHeight=this.getPreferredSize().height;
if(newHeight>table.getRowHeight(行)){
table.setRowHeight(行,this.getPreferredSize().height);
}
归还这个;
}
}
}

我相信我找到了根本原因和解决方案。打印问题源于桌子的高度不正确。表格的高度不正确,因为表格的某些行的高度不正确。有些行的高度错误,因为它们的单元格渲染器没有被JTable调用(也就是说,它们的
gettableCellRenderComponent
方法没有被调用)JTable跳过某些单元格渲染器的原因是优化——它跳过的单元格渲染器用于屏幕外的单元格——屏幕外意味着不需要渲染;JTable在这方面的优化是有意义的

但是,渲染器是程序中唯一设置每个行的正确高度的位置。我选择在单元渲染器中设置行高度在某种程度上是可以理解的,因为单元渲染器处于知道行应该是什么高度的最佳位置

修复此示例程序最直接的方法似乎是在每个单元格渲染器上手动调用
GetTableCellRenderComponent
(这应该在修改表的模型数据后完成)。这使渲染器有机会将表中的每一行设置为其正确的单独高度。各自
for (int colIdx = 0; colIdx < jTable.getColumnCount(); colIdx++)
{
    for (int rowIdx = 0; rowIdx < jTable.getRowCount(); rowIdx++)
    {
        TableColumnModel columnModel = jTable.getColumnModel();
        TableColumn column = columnModel.getColumn(colIdx);
        TableCellRenderer renderer = column.getCellRenderer();
        Object cellValue = jTable.getValueAt(rowIdx, colIdx);
        renderer.getTableCellRendererComponent(jTable, cellValue, 
                    false, false, rowIdx, colIdx);
    }
}
for (int colIdx = 0; colIdx < jTable.getColumnCount(); colIdx++) {
    for (int rowIdx = 0; rowIdx < jTable.getRowCount(); rowIdx++) {
        TableCellRenderer renderer = jTable.getCellRenderer(rowIdx, colIdx);
        Object cellValue = jTable.getValueAt(rowIdx, colIdx);
        renderer.getTableCellRendererComponent(jTable, cellValue,
                false, false, rowIdx, colIdx);
    }
}