How to create and open a pdf integrating tkinter and Reportlabs packages?

Viewed 582

For our research project, my groupmates and I created a pdf file maker code using Reportlabs package stored in a Python file named "PDFCanvas". In another Python file called "AppTest" which contains our tkinter GUI with a button, we copypasted our PDFCanvas File code to try and initialize the creation and viewing of our PDF using the button, which of course works when in a separate file. Apparently, when we run the program in "AppTest", it prompts us with the error: AttributeError: 'str' object has no attribute 'tk'. Can we ask for help as to how we can get it running?

My bad for deleting the first reference working code of the separate PDF creator but here it is:

from reportlab.pdfgen.canvas import Canvas
from reportlab.lib.pagesizes import LETTER
from reportlab.lib.units import inch, cm
from reportlab.pdfgen.canvas import *
from reportlab.lib.colors import *
from reportlab.rl_config import defaultPageSize
from reportlab.pdfbase.pdfmetrics import stringWidth

page_height = defaultPageSize[1]
page_width = defaultPageSize[0]

import os
import sys
import subprocess
import sqlite3

canvas = Canvas("Report - Name [Date].pdf")
canvas.setFont("Helvetica-Bold", 14)
canvas.drawString(72, 795.68, "Veterinary Office")
canvas.save()
subprocess.Popen(['Report - Name [Date].pdf'], shell=True)

UPDATE - Here's a sample of the code that generates the error:

from reportlab.pdfgen.canvas import Canvas
from reportlab.lib.pagesizes import LETTER
from reportlab.lib.units import inch, cm
from reportlab.pdfgen.canvas import *
from reportlab.lib.colors import *
from reportlab.rl_config import defaultPageSize
from reportlab.pdfbase.pdfmetrics import stringWidth

page_height = defaultPageSize[1]
page_width = defaultPageSize[0]

import os
import sys
import sqlite3
import subprocess
import tkinter as tk
import tkinter.ttk as ttk
import tkinter.font as tkFont
from tkinter import *

run = tk.Tk()

def PDFPrint():
    canvas = Canvas("Report - Name [Date].pdf")
    canvas.setFont("Helvetica-Bold", 14)
    canvas.drawString(72, 795.68, "Vet Office")

    canvas.save()
    subprocess.Popen(['Report - Name [Date].pdf'], shell=True)

aButton = Button(run, text = 'Print', command = PDFPrint())

run.mainloop()

For the full error stack:

Traceback (most recent call last):
  File "C:\Users\Desktop\AppTest.py", line 32, in <module>
    aButton = Button(run, text = 'Print', command = PDFPrint())
  File "C:\Users\Desktop\AppTest.py", line 25, in PDFPrint
    canvas = Canvas("Report - Name [Date].pdf")
  File "C:\Program Files\WindowsApps\PythonSoftwareFoundation.Python.3.9_3.9.752.0_x64__qbz5n2kfra8p0\lib\tkinter\__init__.py", line 2688, in __init__
    Widget.__init__(self, master, 'canvas', cnf, kw)
  File "C:\Program Files\WindowsApps\PythonSoftwareFoundation.Python.3.9_3.9.752.0_x64__qbz5n2kfra8p0\lib\tkinter\__init__.py", line 2566, in __init__
    BaseWidget._setup(self, master, cnf)
  File "C:\Program Files\WindowsApps\PythonSoftwareFoundation.Python.3.9_3.9.752.0_x64__qbz5n2kfra8p0\lib\tkinter\__init__.py", line 2535, in _setup
    self.tk = master.tk
AttributeError: 'str' object has no attribute 'tk'
[Finished in 1.3s]

We already preinstalled the ReportLabs Library via pip. I hope I provided adequate information so that answers can be provided to this problem of ours. Thank you!

1 Answers

I figured it out. When importing you used:

from reportlab.pdfgen.canvas import Canvas
...
from tkinter import *

But the problem is that tkinter also defines and overrides the Canvas that was imported from reportlab. That is why you should avoid import *. To fix that issue just change it to import tkinter as tk and then add tk. everywhere you used tkinter widgets/variables. tkinter.Canvas expects a tkinter widget as the first parameter unlike reportlab.pdfgen.canvas.Canvas which expects a string.

Also change this: aButton = Button(run, text = 'Print', command = PDFPrint()) to this:

aButton = Button(run, text = 'Print', command = PDFPrint)

TL;DR You imported Canvas twice and one of the definitions was lost (the one that you wanted to use).

Related