Search code examples
pythonpdfwxpythonwxwidgetswxformbuilder

wxPython/ReportLab: How to create and open a .pdf file on button clicked


Good day all, For about 3days I have been trying hardest to get my way around this! I have a perfectly working wxFrame as well as a perfectly working ReportLab pdf script. See the code files below respectively (Note: data1.py is the GUI while data2.py is the running pdf script). My problems are:- 1) I want the pdf script to run only after I press the “Save To PDF” button 2) The value of the name field (as stored in a variable “NameString”) should be added to the generated pdf file.

At the moment, if I run the script (data2.py) it creates but the Frame and the pdf file (without including the “NameString”) at the same time. That is not what I want, I want the pdf to open and include the “NameString” only after I clicked/press the “Save To PDF” button.

Thanks in advance for your time.

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

Solution

  • Here is a simple working solution I came accross to auto open pdf file generated with ReportLab.

    Import subprocess and ReportLab modules as usual. Then link this function to your event (the magic part of the code is 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!'
    

    Hope this help someone in future search.