Python实现跨平台表格数据分页打印预览处理详解

 更新时间:2025年03月12日 08:32:25   作者:伍华聪  
这篇文章主要为大家详细介绍了如何使用PySide6/PyQt6实现Python跨平台表格数据分页打印预览处理,感兴趣的小伙伴可以跟随小编一起学习一下

我曾经在前面使用WxPython开发跨平台应用程序的时候,写了一篇《WxPython跨平台开发框架之列表数据的通用打印处理》,介绍在WxPython下实现表格数据分页打印处理的过程,在Windows下和MacOS测试效果表现一致。然后在WxPython跨平台的基础上,我利用类似WxPhon的程序框架,使用PySide6/PyQt6实现了另一套跨平台的程序开发,功能上更是比WxPython的实现更加细致和完善了,本篇随笔介绍使用PySide6/PyQt6实现Python跨平台表格数据分页打印预览处理。

1、回顾WxPython的列表数据的通用打印处理

WxPython实现数据的表格预览和打印处理,主要是利用wx.PrintPreviewwx.Printer 和 wx.Printout 等 wxPython 提供的用于打印功能的核心类来处理。

一般列表界面,如下所示。

我们打印模块的处理,需要把这些列表的记录显示在打印预览界面上,并决定是否继续打印即可。

打印预览入口,在列表界面上右键,弹出打印菜单,如下界面所示。

打印预览界面如下所示。

 其打印的逻辑,主要就是调用MyPrintOut的自定义对象,然后调用PrintPreview进行打印预览窗体的显示即可。具体的逻辑还是在自定义的 MyPrintout 类里面。

2、使用PySide6/PyQt6实现Python跨平台表格数据分页打印处理

而使用PySide6/PyQt6实现Python跨平台表格数据分页打印预览处理,逻辑上有所不同,这里没有PrintOut对象来处理了。需要根据表格的TableModel对象来进行数据的分页打印。

在开始介绍实现逻辑前,我们先来看看PySide6/PyQt6实现打印预览的效果。

同样我们是在表格展示上给出通用的打印菜单入口,如上图所示,作为答应预览的统一入口。

而由于数据打印的时候,表格列字段可能有些多有些少,因此最好能够根据表格列选择那些可以打印,那些忽略。而选择后,可以进一步选择横向或者竖向等信息,因此在弹出打印预览前,我们让用户确认一下答应的信息,我订做了一个打印预览前的设置对话框,如下所示。

这样我们可以定制打印的相关信息,也方便我们对打印的格式精细化控制。

对于模型数据很多,这需要考虑到分页的处理,我们需要再实现打印预览的时候,实现分页显示的逻辑,分页打印预览的界面如下所示。

了解了PySide/PyQt的打印预览界面后,我们来分析下实现打印的逻辑处理。

打印预览和打印的时候,我们需要考虑显示器和实际打印设备之间的显示尺寸是不同的,有时候显示器设置显示为200%或其他偏大的数据,如果不注意尺寸的调整,很可能打印预览得到的是一个很小区域的显示内容。

在 PySide6 /PyQt6 中,如果你想实现 QTableView 打印功能并确保兼容不同操作系统(如 macOS 和 Windows)的尺寸变化,你可以使用 QPrinter 和 QPrintDialog 来处理打印。要确保尺寸适应变化,你可以根据打印内容自动调整页面布局。

我编写了一个函数,用于计算缩放比例,如下函数所示。

def calculateScale(self, printer: QPrinter, painter: QPainter) -> float:
        """计算每毫米的逻辑单位"""

        # 获取打印机的 DPI
        ppiPrinterX = printer.resolution()
        ppiPrinterY = ppiPrinterX  # 假设 X 和 Y 方向的 DPI 相同

        # 获取屏幕的 DPI
        screen = QApplication.primaryScreen()
        ppiScreenX = screen.logicalDotsPerInchX()
        ppiScreenY = screen.logicalDotsPerInchY()

        # 计算缩放比例,
        self.logScale = logScale = float(ppiPrinterX) / float(ppiScreenX)

        # 可根据 DPI 比例调整字体大小
        print(f"缩放比例: {logScale}")

        # 获取页面大小和绘制区域大小
        pageRect = printer.pageRect(QPrinter.Unit.DevicePixel)  # 页面大小(像素)
        paintRect = painter.viewport()  # 绘制区域大小(像素)

        # 计算缩放比例
        scale = logScale * float(paintRect.width()) / float(pageRect.width())

        # 设置 QPainter 的缩放比例
        painter.scale(scale, scale)

        # 计算每毫米的逻辑单位
        logUnitsMM = float(ppiPrinterX) / (logScale * 25.4)
        print(f"每毫米的逻辑单位: {logUnitsMM}")
        return logUnitsMM

打印预览的处理,主要就是根据设置对话框,获得横向还是纵向,以及页面大小、标题等信息,然后实现QPreviewDialog里面的paintRequest事件即可,如下预览逻辑处理代码。

def print_preview(self, setting: PrintSetting) -> None:
        """打印预览"""

        # print(setting.__dict__)
        printer = QPrinter()  # QPrinter.PrinterMode.HighResolution

        # 打印的处理
        printer.setPageSize(setting.page_size)
        printer.setPageOrientation(setting.page_orientation)
        self.print_cols = setting.print_cols  # 打印指定列的索引列表
        self.print_title = setting.print_title  # 打印标题
        self.settings = setting  # 保存打印设置

        preview_dialog = QPrintPreviewDialog(printer)
        <strong>preview_dialog.paintRequested.connect(self.print_preview_paint)</strong>
        preview_dialog.exec()

打印预览的处理逻辑,主要就是需要根据缩放的尺寸获得对应的打印区域大小,并根据页面的大小和实现打印的内容显示,计算好尺寸,也就是一般按每页放置多少行,或者每行的高度来计算,如果需要分页,则标识一下即可。

def print_preview_paint(self, printer: QPrinter) -> None:
        """打印预览绘制"""
        self.painter = painter = QPainter(printer)

        # 计算每毫米的逻辑单位
        self.logUnitsMM = self.calculateScale(printer, painter)

        # 获取页面大小
        # unit 参数的可选值有:
        # QPrinter.Unit.Point:点(1 点 = 1/72 英寸)
        # QPrinter.Unit.Millimeter:毫米(常用)
        # QPrinter.Unit.Inch:英寸
        # QPrinter.Unit.Pixel:像素

        # 获取页面的可打印区域
        page_rect = printer.pageRect(QPrinter.Unit.Millimeter)
        self.page_height = page_height = page_rect.height() * self.logUnitsMM
        self.page_width = page_width = page_rect.width() * self.logUnitsMM

如果内容需要分页才能展示完,那么你要使用printer.newPage()来告诉打印机进行分页。

# 分页打印
        print(f"总行数: {total_rows}, 总页数: {total_pages}")
        for page in range(total_pages):
            if page > 0:  # 非第一页,需要换页
                printer.newPage()
            self.print_page(page, rows_per_page, self.print_cols)

        self.painter.end()

打印的时候,我们打印列头和每列内容,都是根据实际的列宽进行一定比例的处理,让它能够兼容打印最佳效果。

打印表头的时候,如下代码。

index = 0  # 用来计算递增的列数
        for col in range(self.columnCount()):
            if print_cols and col not in print_cols:
                continue
            header_text = self.GetColLabelValue(col)
            self.painter.drawText(
                int(x_offset + sum(col_widths[:index])),  # 累计不同的列宽
                y_offset,
                header_text,
            )
            index += 1

打印表格每列的内容,处理规则也是类似,如下代码所示

# 绘制表格内容
        for row in range(
            page * rows_per_page, min((page + 1) * rows_per_page, self.total_rows)
        ):
            y_offset += self.row_height
            index = 0  # 用来计算递增的列数
            for col in range(self.columnCount()):
                if print_cols and col not in print_cols:
                    continue
                # 获取单元格数据
                text = self.GetValue(row, col)
                # 绘制单元格内容
                self.painter.drawText(
                    int(x_offset + sum(col_widths[:index])),  # 累计不同的列宽
                    y_offset,
                    text,
                )
                index += 1

其他如标题,横线、页码等信息,根据显示规则绘制即可。

以上就是Python实现跨平台表格数据分页打印预览处理详解的详细内容,更多关于Python表格数据分页打印的资料请关注脚本之家其它相关文章!

相关文章

  • python人工智能tensorflow函数tensorboard使用方法

    python人工智能tensorflow函数tensorboard使用方法

    这篇文章主要为大家介绍了python人工智能tensorflow函数tensorboard使用方法,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2022-05-05
  • Python模仿POST提交HTTP数据及使用Cookie值的方法

    Python模仿POST提交HTTP数据及使用Cookie值的方法

    这篇文章主要介绍了Python模仿POST提交HTTP数据及使用Cookie值的方法,通过两种不同的实现方法较为详细的讲述了HTTP数据通信及cookie的具体用法,需要的朋友可以参考下
    2014-11-11
  • 使用Python简单实现比较PDF文件差异

    使用Python简单实现比较PDF文件差异

    在处理合同、法律文书或技术文档时,常常会遇到多个版本的同一 PDF,本文将逐步演示如何配置环境并使用示例代码进行比较,还会介绍一些可选的高级设置以满足不同需求,希望对大家有所帮助
    2026-03-03
  • 关于Python中两个不同shape的数组间运算规则

    关于Python中两个不同shape的数组间运算规则

    这篇文章主要介绍了关于Python中两个不同shape的数组间运算规则,众所周知,相同 shape 的两个数组间运算是指两个数组的对应元素相加,我们经常会碰到一些不同 shape 的数组间运算,需要的朋友可以参考下
    2023-08-08
  • Python实现将HTML转换成doc格式文件的方法示例

    Python实现将HTML转换成doc格式文件的方法示例

    这篇文章主要介绍了Python实现将HTML转换成doc格式文件的方法,涉及Python htmlparser及docx模块的相关使用技巧,需要的朋友可以参考下
    2017-11-11
  • Python爬虫动态IP代理使用及防止被封的方法

    Python爬虫动态IP代理使用及防止被封的方法

    在进行网络爬虫时,经常会遇到网站的反爬机制,其中之一就是通过IP封禁来限制爬虫的访问,为了规避这种限制,使用动态IP代理是一种有效的方法,本文将介绍在Python爬虫中如何使用动态IP代理,以及一些防止被封的方法,文中有详细的代码讲解,需要的朋友可以参考下
    2023-11-11
  • python3 mmh3安装及使用方法

    python3 mmh3安装及使用方法

    这篇文章主要介绍了python3 mmh3安装及使用方法,本文给大家介绍的非常详细,具有一定的参考借鉴价值,需要的朋友可以参考下
    2019-10-10
  • Python批量改变图片名字的示例代码

    Python批量改变图片名字的示例代码

    本文主要介绍了Python批量改变图片名字的示例代码,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2022-05-05
  • Python简易版停车管理系统

    Python简易版停车管理系统

    这篇文章主要为大家详细介绍了Python如何实现简易版停车管理系统,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2019-08-08
  • Python+Qt实现智能应用时长统计工具

    Python+Qt实现智能应用时长统计工具

    在数字化生活日益普及的今天,我们每天与各种应用程序的交互时间越来越长,但你是否真正了解自己的数字生活习惯,下面我们就来使用Python和Qt打造智能应用时长统计工具吧
    2025-06-06

最新评论