Search code examples
pythontkintercolorsqr-code

create a qrcode using tkinter


I was trying to create a QRcode generating app in python with tkinter that you enter color and then text and it generates a QRcode but it closes instantly upon startup. (the problem did not happen when I didn't have the color part), (in the future I'm also planning to add a save QR as png button) here's what I have:

from tkinter import *
from tkinter import messagebox
import pyqrcode
from tkinter import colorchooser
import re

def choose_color():
    x = 0
    # variable to store hexadecimal code of color
    color_code = colorchooser.askcolor(title ="Choose color")
    print(color_code)
    x = 1
 
root = Tk()
button = Button(root, text = "Select color",
                   command = choose_color)
button.pack()

if 'x' == 1:
    str = 'color_code' # Your Hex

    match = re.search(r'^#(?:[0-9a-fA-F]{3}){1,2}$', str)

    if match:                      
        print('Hex is valid')
        ws = Tk()
        ws.title("PythonGuides")
        ws.config(bg='color_code')

        def generate_QR():
            if len(user_input.get())!=0 :
                global qr,img
                qr = pyqrcode.create(user_input.get())
                img = BitmapImage(data = qr.xbm(scale=8))
            else:
                messagebox.showwarning('warning', 'All Fields are Required!')
            try:
                display_code()
            except:
                pass

        def display_code():
            img_lbl.config(image = img)
            output.config(text="QR code of " + user_input.get())


        lbl = Label(
            ws,
            text="Enter message or URL",
            bg='color_code'
            )
        lbl.pack()

        user_input = StringVar()
        entry = Entry(
            ws,
            textvariable = user_input
            )
        entry.pack(padx=10)


        button = Button(
            ws,
            text = "generate_QR",
            width=15,
            command = generate_QR
            )
        button.pack(pady=10)

        img_lbl = Label(
            ws,
            bg='color_code')
        img_lbl.pack()
        output = Label(
            ws,
            text="",
            bg='color_code'
            )
        output.pack()
        
        ws.mainloop()

    else:
        print('Hex is not valid')


Solution

  • The reason the program closes immediately is because there is no root.mainloop(). Even if there was, there are a lot of other errors that would prevent the program from working.

    The first problem is if 'x' == 1. Here you are comparing the literal string "x" to the number 1. These are never going to be equal, so the other window will never show up. I can see what you are trying to do with x, but it won't work as you expect. It is better just to get rid of x completely and call a function after the user selects a colour. I've called this function show_qr_window.

    The second problem is how you get the hex code. You use the output of colorchooser.askcolor, which is a tuple containing an rgb tuple representing the colour and it's hex value. You only want the hex value, so you want color_code[1], as the hex value is the second item. I've also added an if statement to make sure color_code is not None. color_code will be None if the user does not choose a colour and just closes the window. If the user has chosen a colour, it is passed to show_qr_window. Because we've checked the user has chosen a colour, you can get rid of all of the other validation as colorchooser will always return a valid hex value. You also no longer have to import re.

    The third issue is that you've used Tk twice. This will cause your program to not work properly. Instead, change ws = Tk() to ws = Toplevel().

    The next issue is str = 'color_code'. This is not how you define a variable. You want to do color_code = 'a string'. In this case, the string is passed to show_qr_window as the variable color, so you can use color_code = color. You also have to change all of the bg = 'color_code' to bg = color_code, as color_code is a variable, not a string.

    The rest of your code seems to work (I haven't tested the qr code generation as I don't have that module installed). Here is the code with all of the fixes:

    from tkinter import *
    from tkinter import messagebox
    import pyqrcode
    from tkinter import colorchooser  
      
    def choose_color():
        # variable to store hexadecimal code of color
        color_code = colorchooser.askcolor(title ="Choose color")
        if color_code != None:
            show_qr_window(color_code[1])
     
    root = Tk()
    button = Button(root, text = "Select color",
                       command = choose_color)
    button.pack()
    root.mainloop()
    
    def show_qr_window(color):                    
        ws = Toplevel()
        color_code = color
        ws.config(bg = color_code)
        def generate_QR():
            if len(user_input.get())!=0 :
                global qr,img
                qr = pyqrcode.create(user_input.get())
                img = BitmapImage(data = qr.xbm(scale=8))
            else:
                messagebox.showwarning('warning', 'All Fields are Required!')
            try:
                display_code()
            except:
                pass
    
        def display_code():
            global img
            img_lbl.config(image = img)
            output.config(text="QR code of " + user_input.get())
    
    
        lbl = Label(
            ws,
            text="Enter message or URL",
            bg=color_code
            )
        lbl.pack()
    
        user_input = StringVar()
        entry = Entry(
            ws,
            textvariable = user_input
            )
        entry.pack(padx=10)
    
    
        button = Button(
            ws,
            text = "generate_QR",
            width=15,
            command = generate_QR
            )
        button.pack(pady=10)
    
        img_lbl = Label(
            ws,
            bg=color_code)
        img_lbl.pack()
        output = Label(
            ws,
            text="",
            bg=color_code
            )
        output.pack()
        
        ws.mainloop()
    

    Assuming generate_QR() and display_code() work as they should (I haven't tested them but they look fine), this code will run as expected.