【问题标题】:wxPython/ReportLab: How to create and open a .pdf file on button clickedwxPython/ReportLab:如何在单击按钮时创建和打开 .pdf 文件
【发布时间】:2014-08-06 02:16:06
【问题描述】:

大家好, 大约 3 天以来,我一直在努力解决这个问题!我有一个完美运行的 wxFrame 以及一个完美运行的 ReportLab pdf 脚本。分别参见下面的代码文件(注意:data1.py 是 GUI,而 data2.py 是正在运行的 pdf 脚本)。 我的问题是:- 1) 我希望 pdf 脚本仅在按下“保存到 PDF”按钮后运行 2) 应将名称字段的值(存储在变量“NameString”中)添加到生成的 pdf 文件中。

目前,如果我运行脚本 (data2.py),它会同时创建 Frame 和 pdf 文件(不包括“NameString”)。这不是我想要的,我希望只有在单击/按下“保存到 PDF”按钮后才能打开 pdf 并包含“NameString”。

提前感谢您的宝贵时间。

data1.py

class MyFrame1 ( wx.Frame ):

    def __init__( self, parent ):
        wx.Frame.__init__ ( self, parent, id = wx.ID_ANY, title = wx.EmptyString, pos = wx.DefaultPosition, size = wx.Size( 250,150 ), style = wx.CAPTION|wx.CLOSE_BOX|wx.MINIMIZE_BOX|wx.SYSTEM_MENU|wx.TAB_TRAVERSAL )

        self.SetSizeHintsSz( wx.DefaultSize, wx.DefaultSize )

        DataBox = wx.BoxSizer( wx.HORIZONTAL )

        gSizer2 = wx.GridSizer( 0, 2, 0, 0 )

        self.NameLabel = wx.StaticText( self, wx.ID_ANY, u"Name", wx.DefaultPosition, wx.DefaultSize, 0 )
        self.NameLabel.Wrap( -1 )
        self.NameLabel.SetFont( wx.Font( 13, 70, 90, 90, False, wx.EmptyString ) )

        gSizer2.Add( self.NameLabel, 0, wx.ALL, 5 )

        self.NameField = wx.TextCtrl( self, wx.ID_ANY, wx.EmptyString, wx.DefaultPosition, wx.DefaultSize, 0 )
        gSizer2.Add( self.NameField, 1, wx.ALL, 5 )

        self.SaveToPDF = wx.Button( self, wx.ID_ANY, u"Save To PDF", wx.DefaultPosition, wx.DefaultSize, 0 )
        gSizer2.Add( self.SaveToPDF, 0, wx.ALL, 5 )


        DataBox.Add( gSizer2, 0, wx.EXPAND|wx.ALIGN_CENTER_VERTICAL, 5 )


        self.SetSizer( DataBox )
        self.Layout()

        self.Centre( wx.BOTH )

        # Connect Events
        self.SaveToPDF.Bind( wx.EVT_BUTTON, self.SaveToPDF_Function )

    def __del__( self ):
        pass


    # Virtual event handlers, overide them in your derived class
    def SaveToPDF_Function( self, event ):
        event.Skip()

data2.py

#!/usr/bin/python
# -*- coding: utf-8 -*- 


import wx
from data1 import MyFrame1

from reportlab.pdfgen import canvas
from reportlab.lib.pagesizes import A3
from reportlab.lib.pagesizes import landscape

import os
import tempfile
import threading



class MyFrame2(MyFrame1):
    def __init__(self, parent):
        MyFrame1.__init__ (self, parent)



    def SaveToPDF_Function( self, event ):

        NameString = self.NameField.GetValue()
        print NameString




file_not_fount = "Selected file doesn't exist!"


class Launcher(threading.Thread):
    def __init__(self,path):
        threading.Thread.__init__(self)
        self.path = 'myFile.pdf'
    def run(self):
        self.open_file(self.path)



    def open_file(self,path):

        if os.path.exists(path):
            if os.name == 'posix':
                subprocess.call(["xdg-open", path])
                #os.popen("evince %s" % path)
            else:
                os.startfile(path)
        else:
            wx.MessageBox(self.file_not_fount,
                          self.title,
                          wx.OK|wx.ICON_INFORMATION)

# NameString = raw_input("Enter ur text: ")

c = canvas.Canvas("myFile.pdf", pagesize=landscape(A3))

c.drawCentredString(600, 800, 'I want this to open only after I clicked the “Save To PDF” button. Also, the text field value (NameString variable) should appear here =>'  + 'NameString' )

c.save()

Launcher('myFile.pdf').start()






app = wx.App(0)
MyFrame2(None).Show()
app.MainLoop()

【问题讨论】:

    标签: python pdf wxpython wxwidgets wxformbuilder


    【解决方案1】:

    这是我遇到的一个简单的工作解决方案,可以自动打开使用 ReportLab 生成的 pdf 文件。

    像往常一样导入子流程和 ReportLab 模块。然后将此函数链接到您的事件(代码的神奇部分是 subprocess.Popen.....)

    def SaveToPDF_Function( self, event ):
    
        NameString = self.NameField.GetValue()
    
        try:
            c = canvas.Canvas("myFile.pdf", pagesize=landscape(A3))
    
            c.drawCentredString(600, 800, 'OPENED... Welcome to ReportLab! This is my FIRST App...'  + NameString )
    
            c.save()
    
            subprocess.Popen(['myFile.pdf'], shell=True)
    
        except IOError:
            print 'The file is already OPENED!'
    

    希望这对将来的搜索有所帮助。

    【讨论】:

      【解决方案2】:

      首先,我将创建reportlab 模块,以便您可以实际调用它。由于它目前已实施,它会在运行时立即创建 PDF。您需要将所有 reportlab 代码放入某种函数中。由于这是一个非常简单的 reportlab 脚本,我只是将它与 wxPython 代码结合起来并删除了线程部分,因此您可以看到一种简单的方法:

      import wx
      
      from reportlab.pdfgen import canvas
      from reportlab.lib.pagesizes import A3
      from reportlab.lib.pagesizes import landscape
      
      class MyFrame1 ( wx.Frame ):
      
          def __init__( self ):
              wx.Frame.__init__ ( self, None, 
                                  size = wx.Size( 250,150 ), 
                                  style = wx.CAPTION|wx.CLOSE_BOX|wx.MINIMIZE_BOX|wx.SYSTEM_MENU|wx.TAB_TRAVERSAL )
      
              self.SetSizeHintsSz( wx.DefaultSize, wx.DefaultSize )
      
              DataBox = wx.BoxSizer( wx.HORIZONTAL )
      
              gSizer2 = wx.GridSizer( 0, 2, 0, 0 )
      
              self.NameLabel = wx.StaticText( self, wx.ID_ANY, u"Name", wx.DefaultPosition, wx.DefaultSize, 0 )
              self.NameLabel.Wrap( -1 )
              self.NameLabel.SetFont( wx.Font( 13, 70, 90, 90, False, wx.EmptyString ) )
      
              gSizer2.Add( self.NameLabel, 0, wx.ALL, 5 )
      
              self.NameField = wx.TextCtrl( self, wx.ID_ANY, wx.EmptyString, wx.DefaultPosition, wx.DefaultSize, 0 )
              gSizer2.Add( self.NameField, 1, wx.ALL, 5 )
      
              self.SaveToPDF = wx.Button( self, wx.ID_ANY, u"Save To PDF", wx.DefaultPosition, wx.DefaultSize, 0 )
              gSizer2.Add( self.SaveToPDF, 0, wx.ALL, 5 )
      
      
              DataBox.Add( gSizer2, 0, wx.EXPAND|wx.ALIGN_CENTER_VERTICAL, 5 )
      
      
              self.SetSizer( DataBox )
              self.Layout()
      
              self.Centre( wx.BOTH )
      
              # Connect Events
              self.SaveToPDF.Bind( wx.EVT_BUTTON, self.SaveToPDF_Function )
      
              self.Show()
      
          #----------------------------------------------------------------------
          def create_pdf(self):
              """"""
              nameString = str(self.NameField.GetValue())
              c = canvas.Canvas("myFile.pdf", pagesize=landscape(A3))
      
              txt = """'I want this to open only after I clicked the "Save To PDF" 
              button. Also, the text field value (NameString variable) should appear 
              here =>'  + %s """ % nameString
              c.drawCentredString(600, 800, txt)
      
              c.save()
      
      
          # Virtual event handlers, overide them in your derived class
          def SaveToPDF_Function( self, event ):
              self.create_pdf()
      
      if __name__ == "__main__":
          app = wx.App(False)
          frame = MyFrame1()
          app.MainLoop()
      

      我推荐阅读以下关于线程和 wxPython 的文章:

      要重新添加线程,我会创建一个线程类,例如您的 Launcher。但是,我会将所有 reportlab 代码放在该类中,当您实例化 Thread 类时,您将传入 namedString

      class Launcher(threading.Thread):
          def __init__(self,path, namedString):
              threading.Thread.__init__(self)
              self.path = 'myFile.pdf'
              self.namedString = namedString
      

      我希望这会有所帮助!

      【讨论】:

      • 感谢您的光临。我无法让 Launcher 类工作?它给了我这个错误消息: Traceback(最近一次调用最后一次):文件“C:\Users\......”,第 105 行,在 Launcher('myFile.pdf').start() TypeError : __init__() 正好接受 3 个参数(给定 2 个)
      • 我是新手,还在学习 wxPython。我应该怎么做才能克服这个问题?
      • 除了 'myFile.pdf' 之外,您还可以将 namedString 传递给它
      • 试试 Launcher("myPdf.pdf", "some string").start()
      • 无论出于何种原因,我无法让上述内容为我工作,但我终于找到了使用“子流程”的出路。我会回答这个以供将来参考。
      猜你喜欢
      • 2016-03-12
      • 2015-10-12
      • 2017-11-05
      • 1970-01-01
      • 2017-07-16
      • 1970-01-01
      • 2012-02-26
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多