pythontkinterbackground-imagetkinter-button

How to make entry fields and buttons transparent while using a background image in Tkinter?


I'm working on a Tkinter project where I have a login screen with a background image. I want to make the entry fields for "Username" and "Password" transparent, so the background image is visible behind them. Additionally, I would like to make the "Login" and "Register" buttons have a transparent background as well, but without affecting their functionality.

I tried using the bg="transparent" option for the entry fields and buttons, but I got an error, since Tkinter does not support transparent backgrounds directly.

enter image description here

Here's code snippet of my current setup:

import tkinter as tk
from tkinter import messagebox
import sqlite3
from PIL import Image, ImageTk  # Pillow modülünü içeri aktar


def setup_database():
    conn = sqlite3.connect("todo_app.db")
    cursor = conn.cursor()
    cursor.execute("""
    CREATE TABLE IF NOT EXISTS users (
        id INTEGER PRIMARY KEY AUTOINCREMENT,
        username TEXT NOT NULL,
        password TEXT NOT NULL
    )
    """)
    cursor.execute("""
    CREATE TABLE IF NOT EXISTS tasks (
        id INTEGER PRIMARY KEY AUTOINCREMENT,
        user_id INTEGER,
        task TEXT NOT NULL,
        completed BOOLEAN NOT NULL DEFAULT 0,
        FOREIGN KEY(user_id) REFERENCES users(id)
    )
    """)
    conn.commit()
    conn.close()


def login_screen():
    def login():
        username = username_entry.get()
        password = password_entry.get()
        conn = sqlite3.connect("todo_app.db")
        cursor = conn.cursor()
        cursor.execute("SELECT id FROM users WHERE username = ? AND password = ?", (username, password))
        user = cursor.fetchone()
        conn.close()

        if user:
            messagebox.showinfo("Başarılı", "Hoşgeldiniz Lordum!")
            main_screen(user[0])  # Kullanıcı ID'sini ana ekrana gönder
        else:
            messagebox.showerror("Hata", "Kullanıcı adı veya şifre yanlış!")

    def register():
        username = username_entry.get()
        password = password_entry.get()
        if username and password:
            conn = sqlite3.connect("todo_app.db")
            cursor = conn.cursor()
            cursor.execute("INSERT INTO users (username, password) VALUES (?, ?)", (username, password))
            conn.commit()
            conn.close()
            messagebox.showinfo("Başarılı", "Kayıt başarılı! Giriş yapabilirsiniz.")
        else:
            messagebox.showerror("Hata", "Kullanıcı adı ve şifre boş olamaz!")

    root = tk.Tk()
    root.title("Giriş Yap")


    width, height = 200, 200  
    screen_width = root.winfo_screenwidth()
    screen_height = root.winfo_screenheight()
    x = (screen_width - width) // 2
    y = (screen_height - height) // 2
    root.geometry(f"{width}x{height}+{x}+{y}")  


    background_image = Image.open("loginbackground.png")  # Resmi yükle
    background_image = background_image.resize((width, height))  
    background_photo = ImageTk.PhotoImage(background_image)  

    background_label = tk.Label(root, image=background_photo)  
    background_label.place(relwidth=1, relheight=1)  
    
    login_frame = tk.Frame(root, bg='white')  
    login_frame.place(relx=0.5, rely=0.5, anchor="center")  

    tk.Label(login_frame, text="Kullanıcı Adı:", fg="black", bg="white").pack(pady=5)
    username_entry = tk.Entry(login_frame, bd=0, relief="flat", highlightthickness=0)  # Borderless entry
    username_entry.pack(pady=5)

    tk.Label(login_frame, text="Şifre:", fg="black", bg="white").pack(pady=5)
    password_entry = tk.Entry(login_frame, show="*", bd=0, relief="flat", highlightthickness=0)  # Borderless entry
    password_entry.pack(pady=5)


    tk.Button(login_frame, text="Giriş Yap", command=login, bd=0, relief="flat", bg="#d3d3d3").pack(pady=5)
    tk.Button(login_frame, text="Kayıt Ol", command=register, bd=0, relief="flat", bg="#d3d3d3").pack(pady=5)

    root.mainloop()


def main_screen(user_id):
    def add_task():
        task = task_entry.get()
        if task:
            conn = sqlite3.connect("todo_app.db")
            cursor = conn.cursor()
            cursor.execute("INSERT INTO tasks (user_id, task) VALUES (?, ?)", (user_id, task))
            conn.commit()
            conn.close()
            task_entry.delete(0, tk.END)
            load_tasks()
        else:
            messagebox.showerror("Hata", "Görev boş olamaz!")

    def delete_task(task_id):
        conn = sqlite3.connect("todo_app.db")
        cursor = conn.cursor()
        cursor.execute("DELETE FROM tasks WHERE id = ?", (task_id,))
        conn.commit()
        conn.close()
        load_tasks()

    def load_tasks():
        for widget in task_frame.winfo_children():
            widget.destroy()
        
        conn = sqlite3.connect("todo_app.db")
        cursor = conn.cursor()
        cursor.execute("SELECT id, task FROM tasks WHERE user_id = ?", (user_id,))
        tasks = cursor.fetchall()
        conn.close()

        for task_id, task in tasks:
            frame = tk.Frame(task_frame)
            frame.pack(fill="x", pady=2)

            tk.Label(frame, text=task).pack(side="left", padx=5)
            tk.Button(frame, text="Sil", command=lambda tid=task_id: delete_task(tid)).pack(side="right")

    root = tk.Tk()
    root.title("Yapılacaklar Listesi")


    width, height = 800, 600  
    screen_width = root.winfo_screenwidth()
    screen_height = root.winfo_screenheight()
    x = (screen_width - width) // 2
    y = (screen_height - height) // 2
    root.geometry(f"{width}x{height}+{x}+{y}")

    task_entry = tk.Entry(root)
    task_entry.pack(pady=5)

    tk.Button(root, text="Ekle", command=add_task).pack(pady=5)

    task_frame = tk.Frame(root)
    task_frame.pack(pady=10)

    load_tasks()
    root.mainloop()

# Programı başlat
if __name__ == "__main__":
    setup_database()
    login_screen()

What I tried: I have tried using the bg="transparent" option for the Entry and Button widgets in Tkinter, hoping to make them transparent. I also removed borders and set their relief property to flat. Additionally, I used the Pillow library to add a background image to the Tkinter window. I have also attempted to remove the default background color of these widgets and experimented with setting different properties like bd=0 and highlightthickness=0.

What I expected: I was expecting the entry fields for the "Username" and "Password" to be transparent so that the background image is visible behind them. Similarly, I expected the "Login" and "Register" buttons to have a transparent background so that the window's background image would show through these UI elements as well.

However, even after applying these changes, I still see a white background behind the entry fields and buttons, which is not the behavior I was expecting.


Solution

  • Using Python 3.12.7, Windows 10

    How to make entry fields and buttons transparent while using a background image in Tkinter?

    Edit: You cannot get Entrys and Buttons widget transparent. Only Label widget you can see it. If you clicked it, it will disappear.

    I do not use sqlite3.

    The problem can be fixed.

    Snippet:

    import tkinter as tk
    from tkinter import messagebox
     
    from PIL import Image, ImageTk  # Pillow modülünü içeri aktar
    
    
     
    
    def login_screen():
        def login():
            username = username_entry.get()
            password = password_entry.get()
             
    
            if user:
                messagebox.showinfo("Başarılı", "Hoşgeldiniz Lordum!")
                main_screen(user[0])  # Kullanıcı ID'sini ana ekrana gönder
            else:
                messagebox.showerror("Hata", "Kullanıcı adı veya şifre yanlış!")
    
        def register():
            username = username_entry.get()
            password = password_entry.get()
            
        root = tk.Tk()
        root.title("Giriş Yap")
        root.wm_attributes('-alpha', 0.5)
         
    
    
        width, height = 200, 200  
        screen_width = root.winfo_screenwidth()
        screen_height = root.winfo_screenheight()
        x = (screen_width - width) // 2
        y = (screen_height - height) // 2
        root.geometry(f"{width}x{height}+{x}+{y}")  
    
    
        background_image = Image.open("p2.png")  # Resmi yükle
        background_image = background_image.resize((width, height))  
        background_photo = ImageTk.PhotoImage(background_image)  
    
        background_label = tk.Label(root, bg='#ab23ff', image=background_photo)  
        background_label.place(relwidth=1, relheight=1)  
        
        #login_frame = tk.Frame(root, bg='#ab23ff',)  
        #login_frame.place(relx=0.5, rely=0.5, anchor="center")  
    
        tk.Label(root, text="Kullanıcı Adı:", fg="black", bg='#ab23ff',).pack(pady=5)
        username_entry = tk.Entry(root, bd=0, fg='white', bg='#ab23ff', relief="flat", highlightthickness=0)  # Borderless entry
        username_entry.pack(pady=5)
    
        tk.Label(root, text="Şifre:", fg="black", bg="white").pack(pady=5)
        password_entry = tk.Entry(root, show="*", fg='white', bg='#ab23ff', bd=0, relief="flat", highlightthickness=0)  # Borderless entry
        password_entry.pack(pady=15)
    
    
        tk.Button(root, text="Giriş Yap", command=login, bg='#ab23ff', bd=0, relief="flat"  ).pack(pady=5)
        tk.Button(root, text="Kayıt Ol", command=register, bg='#ab23ff', bd=0, relief="flat" ).pack(pady=5)
    
        root.mainloop()
    
    
    def main_screen(user_id):
        ....
        ....
        
        root = tk.Toplevel()
        root.title("Yapılacaklar Listesi")
    
        ....
        ....
    
    
        
    
    # Programı başlat
    if __name__ == "__main__":
        #setup_database() 
        login_screen()
    

    Screenshot:

    enter image description here

    Edit: To use Frame widget This is what is look like.

    Screenshot for Frame:

    enter image description here