python-3.xuser-interfacetkinterqr-codevcf-vcard

Python QRCode and TKinter


This is a Python program that creates a GUI with Tkinter and generates a QR code that contains contact information. In the function "generate_qr_code" the values are read from the GUI input fields and checked if "Name", "Surname" and "Tel" are present. Then a QR code object is created with certain settings (version, error correction, box size, border).Contact data in VCARD format is compiled and added to the QR code object. Finally, the QR code is generated, saved to a PNG image and confirmed in the GUI with a message. The GUI is created by placing input fields, labels and buttons. With "root.mainloop()" the GUI is started and runs until it is closed:

import tkinter as tk
import qrcode

def generate_qr_code():
    name =  name_entry.get()
    lastname = lastname_entry.get()
    tel = tel_entry.get()
    org = org_entry.get()
    email = email_entry.get()
    url = url_entry.get()
    street = street_entry.get()
    postal_code = postal_code_entry.get()
    city = city_entry.get()
    country = country_entry.get()
    
    if not (name and lastname and tel):
        result_label.config(text="Name, Surname, and Tel are mandatory.")
        return
    
    qr = qrcode.QRCode(
        version=1,
        error_correction=qrcode.constants.ERROR_CORRECT_M,
        box_size=10,
        border=4,
    )
    
    data = f'''BEGIN:VCARD
    VERSION:3.0
    N:{lastname};{name}
    FN:Displayname
    ORG:{org}
    URL:{url}
    EMAIL:{email}
    TEL;TYPE=voice,work,pref:{tel}
    ADR;TYPE=intl,work,postal,parcel:;;{street};{city};;{postal_code};{country}
    END:VCARD'''
    qr.add_data(data)
    qr.make(fit=True)
    img = qr.make_image(fill_color=(118, 150, 162), back_color=(255, 255, 255))
    img.save("test.png")
    
    result_label.config(text="QR code saved as test.png")

root = tk.Tk()
root.title("QR Code Generator")

name_label = tk.Label(root, text="Name:")
name_entry = tk.Entry(root)

lastname_label = tk.Label(root, text="Surname:")
lastname_entry = tk.Entry(root)

tel_label = tk.Label(root, text="Tel:")
tel_entry = tk.Entry(root)

org_label = tk.Label(root, text="Company:")
org_entry = tk.Entry(root)

email_label = tk.Label(root, text="eMail:")
email_entry = tk.Entry(root)

url_label = tk.Label(root, text="Webseite:")
url_entry = tk.Entry(root)

street_label = tk.Label(root, text="Street:")
street_entry = tk.Entry(root)

postal_code_label = tk.Label(root, text="Postalcode:")
postal_code_entry = tk.Entry(root)

city_label = tk.Label(root, text="City:")
city_entry = tk.Entry(root)

country_label = tk.Label(root, text="Country:")
country_entry = tk.Entry(root)

generate_button = tk.Button(root, text="Generate QR Code", command=generate_qr_code)
result_label = tk.Label(root, text="")

name_label.pack()
name_entry.pack()

lastname_label.pack()
lastname_entry.pack()

tel_label.pack()
tel_entry.pack()

org_label.pack()
org_entry.pack()

email_label.pack()
email_entry.pack()

url_label.pack()
url_entry.pack()

street_label.pack()
street_entry.pack()

postal_code_label.pack()
postal_code_entry.pack()

city_label.pack()
city_entry.pack()

country_label.pack()
country_entry.pack()

generate_button.pack()
result_label.pack()

root.mainloop()

The issue is, a QRCode is been generated, but it doesn't contain any data.

I tried to put in static values to the data variables, but it also generates a QRCode without any data:

import tkinter as tk
import qrcode

def generate_qr_code():
    name =  "John"
    lastname = "Deer"
    tel = "0125454"
    org = "JOHN DEER TRAKTORS"
    email = "John.deer@mail.com"
    url = "Johndeer.com"
    street = "Deer Street 1"
    postal_code = "54368"
    city = "Mannheim"
    country = "Germany"
    
    if not (name and lastname and tel):
        result_label.config(text="Name, Surname, and Tel are mandatory.")
        return
    
    qr = qrcode.QRCode(
        version=1,
        error_correction=qrcode.constants.ERROR_CORRECT_M,
        box_size=10,
        border=4,
    )
    
    data = f'''BEGIN:VCARD
    VERSION:3.0
    N:{lastname};{name}
    FN:Displayname
    ORG:{org}
    URL:{url}
    EMAIL:{email}
    TEL;TYPE=voice,work,pref:{tel}
    ADR;TYPE=intl,work,postal,parcel:;;{street};{city};;{postal_code};{country}
    END:VCARD'''
    qr.add_data(data)
    qr.make(fit=True)
    img = qr.make_image(fill_color=(118, 150, 162), back_color=(255, 255, 255))
    img.save("test.png")
    
    result_label.config(text="QR code saved as test.png")

root = tk.Tk()
root.title("QR Code Generator")

name_label = tk.Label(root, text="Name:")
name_entry = tk.Entry(root)

lastname_label = tk.Label(root, text="Surname:")
lastname_entry = tk.Entry(root)

tel_label = tk.Label(root, text="Tel:")
tel_entry = tk.Entry(root)

org_label = tk.Label(root, text="Company:")
org_entry = tk.Entry(root)

email_label = tk.Label(root, text="eMail:")
email_entry = tk.Entry(root)

url_label = tk.Label(root, text="Webseite:")
url_entry = tk.Entry(root)

street_label = tk.Label(root, text="Street:")
street_entry = tk.Entry(root)

postal_code_label = tk.Label(root, text="Postalcode:")
postal_code_entry = tk.Entry(root)

city_label = tk.Label(root, text="City:")
city_entry = tk.Entry(root)

country_label = tk.Label(root, text="Country:")
country_entry = tk.Entry(root)

generate_button = tk.Button(root, text="Generate QR Code", command=generate_qr_code)
result_label = tk.Label(root, text="")

name_label.pack()
name_entry.pack()

lastname_label.pack()
lastname_entry.pack()

tel_label.pack()
tel_entry.pack()

org_label.pack()
org_entry.pack()

email_label.pack()
email_entry.pack()

url_label.pack()
url_entry.pack()

street_label.pack()
street_entry.pack()

postal_code_label.pack()
postal_code_entry.pack()

city_label.pack()
city_entry.pack()

country_label.pack()
country_entry.pack()

generate_button.pack()
result_label.pack()

root.mainloop()

But the following script does generate a QRCode with data:

import qrcode


qr = qrcode.QRCode(
    version = 1,
    error_correction = qrcode.constants.ERROR_CORRECT_M,
    box_size = 10,
    border = 4,
)

name = input("Name: ")
lastname = input("Surname: ")
tel = input("Tel: ")
org = input("Company: ")
email = input("eMail: ")
url = input("Webseite: ")
street = input("Street: ")
postal_code = input("Postalcode: ")
city = input("City: ")
country = input("Country: ")

print(name + " " + lastname + ", " + tel + ", " + street + ", " + postal_code + " " + city + ", " + country)


data = data = f'''BEGIN:VCARD

VERSION:3.0

N:{lastname};{name}

FN:Displayname

ORG:{org}

URL:{url}

EMAIL:{email}

TEL;TYPE=voice,work,pref:{tel}

ADR;TYPE=intl,work,postal,parcel:;;{street};{city};;{postal_code};{country}

END:VCARD'''
qr.add_data(data)
qr.make(fit=True)

img = qr.make_image(fill_color=(118, 150, 162), back_color=(255, 255, 255))

img.save("test.png")


Solution

  • It is found that qrcode module version 7.4 has issue when the message length is greater than certain size. It works fine when using version 7.3.1.

    The issue in the tkinter version is that there are indentations after the first line of the message which make it not a valid VCARD format. Remove the leading spaces like below:

        data = f"""\
    BEGIN:VCARD
    VERSION:3.0
    N:{lastname};{name}
    FN:Displayname
    ORG:{org}
    URL:{url}
    EMAIL:{email}
    TEL;TYPE=voice,work,pref:{tel}
    ADR;TYPE=intl,work,postal,parcel:;;{street};{city};;{postal_code};{country}
    END:VCARD"""
    

    or using textwrap module:

    import textwrap
    ...
        data = textwrap.dedent(f'''\
        BEGIN:VCARD
        VERSION:3.0
        N:{lastname};{name}
        FN:Displayname
        ORG:{org}
        URL:{url}
        EMAIL:{email}
        TEL;TYPE=voice,work,pref:{tel}
        ADR;TYPE=intl,work,postal,parcel:;;{street};{city};;{postal_code};{country}
        END:VCARD''')
    ...