截断的 JTable 打印输出

2023-12-14

我有一个 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 尚未调用它们的单元格渲染器(即它们的单元格渲染器)。getTableCellRendererComponentJTable 跳过某些单元格渲染器的原因是优化 - 它跳过的单元格渲染器适用于屏幕外的单元格 - 屏幕外意味着不需要渲染; 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(使用前将#替换为@)

截断的 JTable 打印输出 的相关文章

随机推荐

  • Python自引用for循环

    a 0 1 2 3 for a 1 in a print a 1 输出是0 1 2 2 为什么a 1 每次迭代都会改变 您的代码相当于 a 1 a 0 print a 1 a 1 a 1 print a 1 a 1 a 2 print a
  • 如何使用 jQuery 对 :before 选择器进行动画处理

    我有一些带有 before 伪选择器定义的元素 我需要为其添加一些过渡 动画 但在 CSS 中这是不可能的 所以我认为我可以用 jQuery 做到这一点 但有些东西工作不正常 你能帮助我吗 这是我的代码 var pilot remote c
  • 在 PHP 中同一服务器上的多个域之间共享会话

    我需要为我的一个项目实现一种解决方案 其中我有多个域 多个子域 并且它们都需要共享同一个会话 所有域和子域都将指向连接到单个数据库的单个应用程序 意味着如果用户从任何域登录将能够访问应用程序其他域的安全页面 用户可以通过点击链接或在浏览器中
  • 我对 jQuery 中淡入淡出的概念感到困惑

    我正在开发一个在线测试应用程序 并且我正在从 xml文件到jsp页面 所有问题都在jsp中使用for循环显示 现在我不希望所有问题都在一个页面中 而是希望当用户单击 下一步 按钮时将它们一一显示 所以这是我正在使用的代码 它是 仅显示第一个
  • Oracle 的 pro*C 编译器和 gnu C(__builtin_va_list、__attribute__ 等)

    我正在用 pro 编译数据库C 将 ppc 库文件转换为 gcc 可以使用的 c 文件 但是 我在专业版中遇到了很多错误C 像下面这样 PCC S 02201 Encountered the symbol attribute when ex
  • 将 Javascript 数组转换为 Java 数组

    我正在尝试将 Java 中的 Javascript 数组转换为 Java 数组 我正在使用 javax script 包 我在这里测试了这个例子 但是类型 NativeArray 未被识别 https stackoverflow com a
  • Yii2:用 Sweet Alert 替换 Gridview 使用的默认确认消息

    我在用yii2mod yii2 sweet alert在我的项目中 我在基本和高级主题上使用它 我喜欢它 问题 如何更改网格默认确认对话框 普通 JavaScript 确认 以便使用甜蜜警报为了让它看起来更好 我已经尝试修改按钮的删除模板
  • PHP - 获取 ADODB 中受影响的行

    我使用 ADODB 创建到数据库的连接 我更新了数据库中的数据 没有错误 问题是我无法通过以下方式获取受影响的行数Affected Rows 我尝试使用非常简单的代码 但它不起作用 这是我的代码 sql UPDATE User SET Na
  • 异常:无法在控制器管理的 UINavigationBar 上手动设置委托

    我的应用程序从登录屏幕开始 然后继续CreateRequestTableViewController 并且所有内容都嵌入在导航控制器中 因此后退按钮CreateRequestvc 返回到登录屏幕 我想询问用户在注销之前是否确定自己是这样 并
  • 如何在C++ OpenCV中将图像(Mat)转换为inputArray?

    我想对灰度图像的强度值应用 k 均值聚类 我对如何将像素表示为向量感到非常困惑 所以如果我的形象是H x W像素 那么我的向量应该是H W维度 我尝试过的是 int myClass myFunction const cv Mat img c
  • 将 PDF 加载到 android webview 中

    in my android我必须加载的应用程序PDFs在服务器中进入webview 根据我使用的堆栈溢出问题谷歌文档视图在加载它时 但我的问题是有时它不显示文件webview而在另一个例子中它显示得很好 我无法弄清楚问题所在 但代码看起来没
  • genymotion:“player.exe 停止工作”

    我从他们的官方网站安装了 Windows 7 版的 GENYMOTION 软件包 它为我安装了 Oracle VM VirtualBox 和 Genymotion 之后 我打开 VirtualBox 然后打开 Genymotion 下载 G
  • 如何访问 WordPress.com 网站的 WP REST API?

    我看到 WordPress com 最近开始使用 Gutenberg 它依赖于 WP REST API 我正在构建一个插件 我想使用自托管站点中的 WP REST API 并让它与 WordPress com 站点通信 但我在查找 REST
  • 使用 jQuery 进行主动导航 - 无法将默认类应用于锚点

    我目前正在尝试制作一个navigation menu其中一个active class应用于锚点 其href与当前 URL 匹配的属性 因此我可以设置该锚点的样式 使其从菜单的其余部分中脱颖而出 这是我的标记 div h2 Navigatio
  • bodyParser 似乎不起作用

    抱歉 如果这个问题听起来 简单 但我不明白body parser处理这个非常简单的例子 use strict const PORT 3000 const express require express const bodyParser re
  • 所有时区时间都在哪里维护?

    如果我们设置TimeZone对于特定的Date java如何为此设置时间Date 例如如果我们设置PST作为时区 它如何知道确切的时区 它在哪里维护 提前致谢 时区数据源是特定于实现的 但我相信大多数实现都使用IANA 数据库 又名 zon
  • D3 折线图/面积图可以处理无序数据吗?

    请参考以下链接 https bl ocks org mbostock 34f08d5e11952a80609169b7917d4172 这里的数据是有序的 按顺序 如 2000 年 1 月 2000 年 2 月等 但我想让这个 d3 图适用
  • 有没有办法修复错误“不会尝试重新连接。原因:数据库位于不同的区域。”在带有 Firebase 的 Android Studio 中

    当我尝试在我的应用程序中注册时 进度条会无休止地运行 因为我的应用程序无法访问数据库 我尝试了一些获取更新的解决方案googles services json文件并更改我的代码中的 URL 但似乎没有任何效果 出现的错误 W Persist
  • Git 非快进拒绝

    我觉得这个问题已经被问过很多次了 但解决方案通常是 我删除了目录并通过新的签出重新完成了工作 我进行了提交并推送 但意识到我在提交消息中引用了错误的票号 所以我快速查看了一下solution最后在终端中输入以下内容 git reset so
  • 截断的 JTable 打印输出

    我有一个 JTable 它使用 JTextArea 作为其 TableCellRenderer 以便表格单元格可以利用自动换行 JTable 显示正常 当我通过 JTable 将表格打印到打印机时打印方法 输出总是在大约 60 的数据处被截