欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

WxPython開發(fā)之列表數(shù)據(jù)的自定義打印處理

 更新時(shí)間:2025年03月12日 08:22:16   作者:伍華聰  
這篇文章主要為大家詳細(xì)介紹了如何利用WxPython內(nèi)置的打印數(shù)據(jù)組件實(shí)現(xiàn)列表數(shù)據(jù)的自定義打印處理,以及對記錄進(jìn)行分頁等常規(guī)操作,需要的可以參考下

在WxPython跨平臺開發(fā)框架中,我們大多數(shù)情況下,數(shù)據(jù)記錄通過wx.Grid的數(shù)據(jù)表格進(jìn)行展示,其中表格的數(shù)據(jù)記錄的顯示和相關(guān)處理,通過在基類窗體 BaseListFrame 進(jìn)行統(tǒng)一的處理,因此對于常規(guī)的數(shù)據(jù)記錄打印,我們也可以在其中集成相關(guān)的打印處理,本篇隨筆介紹如何利用WxPython內(nèi)置的打印數(shù)據(jù)組件實(shí)現(xiàn)列表數(shù)據(jù)的自定義打印處理,以及對記錄進(jìn)行分頁等常規(guī)操作。

1、WxPython內(nèi)置的打印數(shù)據(jù)組件

wx.PrintPreview、wx.Printer 和 wx.Printout 是 wxPython 提供的用于打印功能的核心類。它們幫助開發(fā)者在程序中實(shí)現(xiàn)打印和打印預(yù)覽功能。下面是關(guān)于這三個(gè)類的詳細(xì)介紹及其使用方法。

wx.Printout

wx.Printout 是一個(gè)抽象類,通常需要被子類化以便在打印時(shí)自定義頁面內(nèi)容。你可以通過繼承 wx.Printout 類來實(shí)現(xiàn)自定義打印內(nèi)容,重寫 OnPrintPage 方法來決定每一頁的打印內(nèi)容。

常用方法:

  • OnPrintPage(page): 該方法是打印過程中每一頁的核心方法。你需要在這里繪制要打印的內(nèi)容,例如文本、圖片、圖形等。每次頁面需要繪制時(shí),該方法會被調(diào)用。
  • GetDC(): 獲取一個(gè)打印設(shè)備上下文(wx.DC 對象),用于在頁面上繪制內(nèi)容。
  • HasPage(page): 該方法用于檢查是否有足夠的內(nèi)容來填充打印頁面,返回 True 或 False

簡單的wx.PrintOut的子類繼承處理如下所示。

import wx

class MyPrintout(wx.Printout):
    def __init__(self):
        super().__init__()

    def OnPrintPage(self, page):
        dc = self.GetDC()
        dc.SetFont(wx.Font(10, wx.FONTFAMILY_SWISS, wx.FONTSTYLE_NORMAL, wx.FONTWEIGHT_NORMAL))
        dc.DrawText("Hello, this is a print test!", 100, 100)
        return True

一般情況下,我們肯定會添加很多相關(guān)的繪制邏輯處理,這里只是簡單的介紹。

wx.Printer

wx.Printer 是用來執(zhí)行實(shí)際打印操作的類。它用于與打印機(jī)進(jìn)行交互,發(fā)送頁面內(nèi)容到打印機(jī)。你可以使用 wx.Printer 來選擇打印機(jī)、啟動(dòng)打印作業(yè)并發(fā)送打印內(nèi)容。

常用方法:

  • Print(printout): 用于啟動(dòng)打印操作,將 printout 對象中的內(nèi)容發(fā)送到打印機(jī)。
  • GetCurrentPrinterName(): 獲取當(dāng)前選定的打印機(jī)名稱。
  • SetPageSize(width, height): 設(shè)置打印頁面的大小。
  • SetPrintData(print_data): 設(shè)置打印的數(shù)據(jù),控制打印的紙張大小、打印質(zhì)量等

wx.PrintPreview

wx.PrintPreview 用于實(shí)現(xiàn)打印預(yù)覽功能,它允許你查看打印內(nèi)容的預(yù)覽,而不是直接將內(nèi)容發(fā)送到打印機(jī)。通過打印預(yù)覽,你可以看到打印文檔的外觀,并進(jìn)行調(diào)整(如分頁、內(nèi)容布局等)。

常用方法:

  • IsOk(): 檢查打印預(yù)覽是否成功創(chuàng)建。
  • Show(): 顯示打印預(yù)覽窗口。
  • SetPagesPerPreview(pages): 設(shè)置每個(gè)預(yù)覽頁面顯示的頁面數(shù)。

通常,wx.PrintPreview 是在打印機(jī)選擇之前使用的,它會展示打印內(nèi)容的預(yù)覽。預(yù)覽確認(rèn)后,用戶可以選擇繼續(xù)打印,程序則使用 wx.Printer 實(shí)際執(zhí)行打印操作。

繪制二維表的打印預(yù)覽可以通過在 wx.Printout 類的 OnPrintPage 方法中逐行逐列繪制表格內(nèi)容。為了實(shí)現(xiàn)更復(fù)雜的表格布局,通常需要計(jì)算每一行和每一列的位置,確保文本不會超出頁面邊界,并在必要時(shí)分頁。

如果需要在 wxPython 中實(shí)現(xiàn)打印預(yù)覽,可以使用 wx.PrintPreview 類來生成打印預(yù)覽。這個(gè)類允許你在顯示打印預(yù)覽時(shí),不直接打印內(nèi)容,而是顯示一個(gè)打印的“模擬”視圖,用戶可以在此視圖中查看打印效果,決定是否繼續(xù)打印。

高級功能:表格樣式

如果你需要更復(fù)雜的表格樣式(例如,添加邊框、背景色或其他格式化功能),你可以通過 dc.SetPen()、dc.SetBrush() 等方法來實(shí)現(xiàn)。

示例:給表格添加邊框

def draw_table_border(dc, x_pos, y_pos, width, height):
    dc.SetPen(wx.Pen(wx.Colour(0, 0, 0)))  # 設(shè)置邊框顏色
    dc.SetBrush(wx.Brush(wx.Colour(255, 255, 255)))  # 設(shè)置背景顏色
    dc.DrawRectangle(x_pos, y_pos, width, height)

你可以在 OnPrintPage 方法中調(diào)用此函數(shù),為每個(gè)單元格添加邊框。

2、在框架的基類窗體中實(shí)現(xiàn)自定義打印及分頁處理

在我的WxPython跨平臺開發(fā)框架中,我們對于常規(guī)窗體列表界面做了抽象處理,一般絕大多數(shù)的邏輯封裝在基類上,基類提供一些可重寫的函數(shù)給子類實(shí)現(xiàn)彈性化的處理。

如下是基類窗體和其他窗體之間的集成關(guān)系。

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

我們打印模塊的處理,需要把這些列表的記錄顯示在打印預(yù)覽界面上,并決定是否繼續(xù)打印即可。

前面介紹了wx.PrintOut的子類處理,只是簡單的輸出一些文本信息,一般對于更復(fù)雜的打印需求(例如表格或多頁文檔),你可以在 OnPrintPage 中使用更復(fù)雜的繪制邏輯。例如,繪制多個(gè)表格行或根據(jù)頁數(shù)拆分內(nèi)容等等。

我們先來看看實(shí)現(xiàn)后的打印預(yù)覽界面效果,有一個(gè)感官認(rèn)識后再繼續(xù)探尋它的實(shí)現(xiàn)機(jī)制。

打印預(yù)覽入口,在列表界面上右鍵,彈出打印菜單,如下界面所示。

打印預(yù)覽界面如下所示。

我們來看看,對于列表數(shù)據(jù),我們是如何一步步通過自定義的方式實(shí)現(xiàn)打印的內(nèi)容繪制的。

打印有幾個(gè)注意的地方,由于不同的操作系統(tǒng)或者不同的設(shè)置可能會導(dǎo)致打印面板的尺寸有所差異,因此最好統(tǒng)一轉(zhuǎn)換為一個(gè)邏輯的尺寸處理;另外分頁的處理是關(guān)鍵,需要根據(jù)字體文字計(jì)算出你繪制一行所需要的高度,然后根據(jù)操作的頁面高度計(jì)算可以繪制的行數(shù),然后在表格行記錄中循環(huán)處理,判斷達(dá)到每頁的行數(shù)就換行即可。

在我們的WxPython跨平臺框架中列表入口菜單的實(shí)現(xiàn)如下代碼所示,主要就是調(diào)用MyPrintOut的自定義對象,然后調(diào)用PrintPreview進(jìn)行打印預(yù)覽窗體的顯示即可,如下代碼所示。

def OnPrint(self, event: wx.Event) -> None:
        """打印表格"""

        # 創(chuàng)建打印數(shù)據(jù)對象
        pageData = wx.PrintData()
        pageData.SetPaperId(wx.PAPER_A4)  # 設(shè)置紙張類型為 A4
        pageData.SetOrientation(wx.LANDSCAPE)  # 設(shè)置紙張方向?yàn)榭v向

        # 將打印數(shù)據(jù)設(shè)置到打印機(jī)對象
        data = wx.PrintDialogData(pageData)
        # 窗口標(biāo)題
        page_title = self.GetTitle()

        # 創(chuàng)建打印輸出對象
        printout = ctrl.MyPrintout(self.grid, page_title)
        printout2 = ctrl.MyPrintout(self.grid, page_title)

        # 創(chuàng)建打印機(jī)對象,并將打印數(shù)據(jù)傳遞給打印機(jī)
        # printer = wx.Printer(data)
        preview = wx.PrintPreview(printout, printout2, data=data)
        if preview.IsOk():
            preview.SetZoom(100)
            frame = wx.PreviewFrame(
                preview, self, "打印預(yù)覽", pos=self.GetPosition(), size=self.GetSize()
            )
            frame.Initialize()
            frame.Show(True)

wx.PrintPreview需要接受兩個(gè)PrintOut對象,如代碼:printout, printout2

wx.PrintData 主要就是指定頁面尺寸及布局等相關(guān)信息,具體的邏輯還是在自定義的 MyPrintout 類里面,它接受當(dāng)前的wx.Grid對象和當(dāng)前頁面的標(biāo)題。

而ctrl.MyPrintOut是我們根據(jù)需要打印的二維表內(nèi)容進(jìn)行的邏輯封裝,它們的類初始化代碼如下。

class MyPrintout(wx.Printout):
    """創(chuàng)建一個(gè)自定義的 wx.Printout 類,在其中定義如何打印 wx.Grid 的內(nèi)容。"""

    def __init__(
        self,
        grid: gridlib.Grid,
        title: str = "打印標(biāo)題",
        margins=(wx.Point(10, 10), wx.Point(10, 10)),
    ):
        super().__init__()
        self.grid = grid
        self.title = title
        self.margins = margins

        # 獲取網(wǎng)格的行列數(shù)
        self.row_count = self.grid.GetNumberRows()
        self.col_count = self.grid.GetNumberCols()
        self.current_row = 0  # 記錄當(dāng)前打印的行數(shù)

我們記錄表格對象,以及表格的行數(shù)和列數(shù),以及當(dāng)前打印的行數(shù),默認(rèn)從0開始,在每次計(jì)算分頁的時(shí)候,需要知道當(dāng)前的記錄才能接著繪制剩余的記錄。

我們通過轉(zhuǎn)換邏輯單位,獲得繪制設(shè)備的頁面高度和寬度,然后每行記錄的高度,我們根據(jù)內(nèi)容的實(shí)際高度+一定的空白間距,如下代碼

font = wx.Font(
            FONTSIZE, wx.FONTFAMILY_TELETYPE, wx.FONTSTYLE_NORMAL, wx.FONTWEIGHT_NORMAL
        )
        dc.SetFont(font)
        # 計(jì)算每行的高度
        self.lineHeight = dc.GetCharHeight() + 5  # 加上5像素的間距

計(jì)算每頁可以繪制多少行,需要記錄摒除標(biāo)題內(nèi)容、表格標(biāo)題行以及相關(guān)空白,剩下的頁面高度除以一行的高度,進(jìn)行計(jì)算獲得即可。如下代碼所示。

# 標(biāo)題高度 + 標(biāo)題底部空白行高度 + 表頭高度
        y_offset = 20 + 20 + 20
        # 計(jì)算每頁可以顯示的行數(shù)
        self.linesPerPage = int((self.pageHeight - y_offset) // self.lineHeight)

然后,我們在PrintOut的子類實(shí)現(xiàn)中重寫 OnPreparePrinting(self) 函數(shù),這個(gè)函數(shù)在繪制頁面前執(zhí)行一次,我們需要在其中計(jì)算出頁面的數(shù)量。

# 計(jì)算頁面數(shù)
        self.numPages = self.row_count // self.linesPerPage
        if self.row_count % self.linesPerPage != 0:
            self.numPages += 1

然后在重寫兩個(gè)函數(shù),決定是否存在下一頁,以及頁碼信息,如下所示的函數(shù)實(shí)現(xiàn)。

def HasPage(self, page):
        return page <= self.numPages

    def GetPageInfo(self):
        return (1, self.numPages, 1, self.numPages)

剩下的就是實(shí)現(xiàn)

def OnPrintPage(self, page: int) -> bool:

這個(gè)函數(shù)就是主要控制繪制內(nèi)容和分頁標(biāo)識的處理的。

繪制的內(nèi)容,主要根據(jù)起始位置,并設(shè)置相關(guān)的字體大小實(shí)現(xiàn)繪制即可,我們簡單介紹一下,如下是在頁面頂部的中間繪制標(biāo)題。

# 繪制標(biāo)題,居中顯示
        text_width, text_height = dc.GetTextExtent(self.title)
        title_x = (width - text_width) // 2  # 計(jì)算居中的X位置
        dc.DrawText(self.title, int(title_x), int(y_offset))

線條的繪制也是類似,確定位置和顏色等,畫線繪制即可。

# 設(shè)置線條顏色
        dc.SetPen(wx.Pen(wx.Colour(0, 0, 0)))  # 黑色線條
        # 將所有的坐標(biāo)轉(zhuǎn)換為整數(shù)
        dc.DrawLine(line_x, line_y, line_x + line_width, line_y)

繪制表頭的時(shí)候,我們切換會正常的字體大小,然后遍歷繪制

# 繪制表頭
        font.SetPointSize(FONTSIZE)
        dc.SetFont(font)
        for col in range(self.col_count):
            dc.DrawText(
                self.grid.GetColLabelValue(col),
                int(x_offset + sum(col_widths[:col])),
                int(y_offset),
            )

其中的 col_widths 是我們前面根據(jù)表格的列數(shù)量進(jìn)行計(jì)算的寬度集合

col_widths = [self.grid.GetColSize(col) for col in range(self.col_count)]

以上內(nèi)容是我們每頁都需要繪制的常規(guī)信息,因此先繪制報(bào)表表頭、線條、表格標(biāo)題行這些。

下面我們需要根據(jù)當(dāng)前page的頁碼來計(jì)算當(dāng)前開始的行記錄,page為1的時(shí)候,那么當(dāng)前的開始行號是0,否則就是根據(jù)頁碼計(jì)算數(shù)值。

self.current_row = (page - 1) * self.linesPerPage  # 計(jì)算當(dāng)前頁面的起始行數(shù)

下面就是對數(shù)據(jù)進(jìn)行分頁的處理了,如果需要分頁,在OnPrintPage函數(shù)中返回False,否則返回True,如下代碼所示。

# 繪制表格的內(nèi)容
        lines_on_page = 0  # 記錄當(dāng)前頁面的行數(shù)
        for row in range(self.current_row, self.row_count):
            y_offset += self.lineHeight  # 增加行的高度
            for col in range(self.col_count):
                cell_value = self.grid.GetCellValue(row, col)
                dc.DrawText(
                    cell_value,
                    x_offset + sum(col_widths[:col]),
                    y_offset,
                )
            lines_on_page += 1
            # 如果當(dāng)前頁面的行數(shù)已經(jīng)達(dá)到最大值,則繪制頁腳,并返回False,繼續(xù)打印下一頁
            if lines_on_page >= self.linesPerPage:
                self.draw_footer(dc, page) # 繪制頁腳,底部的頁碼
                return False  # 打印完一頁后返回False,繼續(xù)打印下一頁

        self.draw_footer(dc, page)
        return True

而底部的頁碼信息,我們簡單繪制當(dāng)前頁面和頁面總數(shù)即可,如下函數(shù)。

def draw_footer(self, dc: wx.DC, page: int):
        # 繪制當(dāng)前頁碼
        page_num_text = f"當(dāng)前頁碼: {page} / {self.numPages}"
        page_num_width, page_num_height = dc.GetTextExtent(page_num_text)
        dc.DrawText(
            page_num_text,
            int((self.pageWidth - page_num_width) // 2),
            int(self.y2),
        )

最后獲得隨筆開始前介紹的效果。

如果沒有分頁信息,那么底部空白一些,還是會繪制頁碼信息,如下是沒有更多記錄的時(shí)候打印預(yù)覽的界面效果

以上就是整個(gè)實(shí)現(xiàn)的過程,我們在WxPython開發(fā)框架中自定義PrintOut對象,實(shí)現(xiàn)WxPython跨平臺開發(fā)框架之列表數(shù)據(jù)的通用打印處理過程。

到此這篇關(guān)于WxPython開發(fā)之列表數(shù)據(jù)的自定義打印處理的文章就介紹到這了,更多相關(guān)WxPython列表數(shù)據(jù)打印內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Python?pandas刪除指定行/列數(shù)據(jù)的方法實(shí)例

    Python?pandas刪除指定行/列數(shù)據(jù)的方法實(shí)例

    這篇文章主要給大家介紹了關(guān)于Python?pandas刪除指定行/列數(shù)據(jù)的相關(guān)資料,文中通過實(shí)例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2022-01-01
  • 使用python字典統(tǒng)計(jì)CSV數(shù)據(jù)的步驟和示例代碼

    使用python字典統(tǒng)計(jì)CSV數(shù)據(jù)的步驟和示例代碼

    為了使用Python字典來統(tǒng)計(jì)CSV數(shù)據(jù),我們可以使用內(nèi)置的csv模塊來讀取CSV文件,并使用字典來存儲統(tǒng)計(jì)信息,以下是一個(gè)詳細(xì)的步驟和完整的代碼示例,需要的朋友可以參考下
    2024-12-12
  • 淺談Keras參數(shù) input_shape、input_dim和input_length用法

    淺談Keras參數(shù) input_shape、input_dim和input_length用法

    這篇文章主要介紹了淺談Keras參數(shù) input_shape、input_dim和input_length用法,具有很好的參考價(jià)值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2020-06-06
  • PyQt使用QPropertyAnimation開發(fā)簡單動(dòng)畫

    PyQt使用QPropertyAnimation開發(fā)簡單動(dòng)畫

    這篇文章主要介紹了PyQt使用QPropertyAnimation開發(fā)簡單動(dòng)畫,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-04-04
  • 淺談Python類的單繼承相關(guān)知識

    淺談Python類的單繼承相關(guān)知識

    本文給大家介紹面向?qū)ο笕刂焕^承Inheritance的相關(guān)知識,通過示例代碼給大家介紹了繼承、貓類、狗類不用寫代碼,直接繼承了父類的屬性和方法,具體實(shí)現(xiàn)代碼跟隨小編一起看看吧
    2021-05-05
  • python中編寫函數(shù)并調(diào)用的知識點(diǎn)總結(jié)

    python中編寫函數(shù)并調(diào)用的知識點(diǎn)總結(jié)

    在本篇文章里小編給各位整理的是一篇關(guān)于python中編寫函數(shù)并調(diào)用的知識點(diǎn)總結(jié)內(nèi)容,有興趣的朋友們可以學(xué)習(xí)下。
    2021-01-01
  • Python四大金剛之元組詳解

    Python四大金剛之元組詳解

    這篇文章主要介紹了Python的元組,小編覺得這篇文章寫的還不錯(cuò),需要的朋友可以參考下,希望能夠給你帶來幫助
    2021-10-10
  • 利用PyQt5制作一個(gè)豆瓣電影信息查看器

    利用PyQt5制作一個(gè)豆瓣電影信息查看器

    這篇文章主要介紹了如何通過PyQt5制作一個(gè)查看器,可以查看豆瓣前100名電影的信息,當(dāng)然這個(gè)爬取信息比較簡單。感興趣的小伙伴可以試一試
    2022-01-01
  • Python使用sqlite3模塊內(nèi)置數(shù)據(jù)庫

    Python使用sqlite3模塊內(nèi)置數(shù)據(jù)庫

    這篇文章主要介紹了Python使用sqlite3模塊內(nèi)置數(shù)據(jù)庫,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2020-05-05
  • python3 pandas 讀取MySQL數(shù)據(jù)和插入的實(shí)例

    python3 pandas 讀取MySQL數(shù)據(jù)和插入的實(shí)例

    下面小編就為大家分享一篇python3 pandas 讀取MySQL數(shù)據(jù)和插入的實(shí)例,具有很好的參考價(jià)值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2018-04-04

最新評論