我有一个 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;
}
}
}
我相信我找到了根本原因和解决方案。打印问题源于桌子高度错误。该表格的高度错误,因为表格的某些行的高度错误。某些行的高度不正确,因为 JTable 尚未调用它们的单元格渲染器(即它们的单元格渲染器)。getTableCellRendererComponent
JTable 跳过某些单元格渲染器的原因是优化 - 它跳过的单元格渲染器适用于屏幕外的单元格 - 屏幕外意味着不需要渲染; JTable在这方面的优化是有道理的。
然而,渲染器是程序中唯一设置每个单独行的正确高度的地方。我选择在单元格渲染器中设置行高是可以理解的,因为单元格渲染器处于了解行高度的最佳位置。
修复此示例程序的最直接方法似乎是手动调用getTableCellRendererComponent
在每个单元格渲染器上(这应该在修改表的模型数据之后完成。)这使渲染器有机会将表中的每一行设置为其正确的单独高度。当每一行都处于正确的高度时,JTable 总体上最终会达到正确的高度,这似乎解决了打印截断问题。以下代码显示了访问所有渲染器来执行此操作:
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);
}
}
这种对所有单元格渲染器的手动访问绕过了 JTable 仅调用屏幕单元格的单元格渲染器的优化。因此,您可能只想在用户请求打印之后(但在调用 JTable 上的打印方法之前)执行此解决方法代码。如果用户只是使用 GUI 而不是打印,这可以让 JTable 优化保持有效。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)