wxPython/ReportLab: วิธีสร้างและเปิดไฟล์ .pdf เมื่อคลิกปุ่ม

สวัสดีทุกคน เป็นเวลาประมาณ 3 วันแล้วที่ฉันพยายามอย่างหนักเพื่อแก้ไขปัญหานี้! ฉันมี wxFrame ที่ทำงานได้อย่างสมบูรณ์แบบ รวมถึงสคริปต์ ReportLab pdf ที่ทำงานได้อย่างสมบูรณ์แบบ ดูไฟล์โค้ดด้านล่างตามลำดับ (หมายเหตุ: data1.py คือ GUI ในขณะที่ data2.py เป็นสคริปต์ pdf ที่ทำงานอยู่) ปัญหาของฉันคือ:- 1) ฉันต้องการให้สคริปต์ pdf ทำงานหลังจากที่ฉันกดปุ่ม "บันทึกเป็น PDF" เท่านั้น 2) ควรเพิ่มค่าของฟิลด์ชื่อ (ตามที่เก็บไว้ในตัวแปร "NameString") ลงในไฟล์ pdf ที่สร้างขึ้น ไฟล์.

ในขณะนี้ หากฉันเรียกใช้สคริปต์ (data2.py) มันจะสร้างแต่เฟรมและไฟล์ pdf (ไม่รวม “NameString”) ในเวลาเดียวกัน นั่นไม่ใช่สิ่งที่ฉันต้องการ ฉันต้องการให้เปิด PDF และรวม "NameString" หลังจากที่ฉันคลิก/กดปุ่ม "บันทึกเป็น PDF" เท่านั้น

ขอขอบคุณล่วงหน้าสำหรับเวลาของคุณ

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()

person Umar Yusuf    schedule 16.06.2014    source แหล่งที่มา


คำตอบ (2)


นี่เป็นวิธีแก้ปัญหาการทำงานง่ายๆ ที่ฉันเจอกับไฟล์ PDF ที่เปิดอัตโนมัติที่สร้างด้วย ReportLab

นำเข้ากระบวนการย่อยและโมดูล 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!'

หวังว่านี่จะช่วยใครบางคนในการค้นหาในอนาคต

person Umar Yusuf    schedule 29.06.2014

ก่อนอื่น ฉันจะสร้างโมดูล 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

ฉันหวังว่านี่จะช่วยได้!

person Mike Driscoll    schedule 16.06.2014
comment
ขอบคุณที่แวะมา ฉันไม่สามารถทำให้คลาส Launcher ทำงานได้หรือไม่ มันแจ้งข้อความแสดงข้อผิดพลาดนี้แก่ฉัน: Traceback (การโทรล่าสุดครั้งล่าสุด): File C:\Users\......, บรรทัด 105 ใน ‹module› Launcher('myFile.pdf').start() TypeError: __init__ () รับ 3 ข้อโต้แย้ง (ให้ 2 ข้อ) - person Umar Yusuf; 17.06.2014
comment
ฉันยังใหม่และยังคงเรียนรู้ wxPython ฉันควรทำอย่างไรเพื่อเอาชนะสิ่งนี้? - person Umar Yusuf; 17.06.2014
comment
คุณจะส่งผ่านชื่อ String นอกเหนือจาก 'myFile.pdf' - person Mike Driscoll; 17.06.2014
comment
ลองใช้ Launcher(myPdf.pdf, some string).start() - person Mike Driscoll; 19.06.2014
comment
ไม่ว่าด้วยเหตุผลใดก็ตามฉันไม่สามารถทำให้สิ่งที่กล่าวมาข้างต้นใช้งานได้ แต่ในที่สุดฉันก็มีทางออกโดยใช้ "กระบวนการย่อย" ฉันจะตอบคำถามนี้เพื่อใช้อ้างอิงในอนาคต - person Umar Yusuf; 29.06.2014