Seite 1 von 1

TKINTER GUI Freeze

Verfasst: Montag 24. Juli 2023, 01:55
von mork
Moin, ich wollte ein AutoClicker Programmieren mit einem GUI. Wenn ich diesen jetzt Starte, dann freezed er nachdem ich den Key drücke. Ich kann mir das leider nicht selbst erklären und würde mich auf hilfe freuen. (Bin neu in Python und coding generell.)

Code: Alles auswählen

import tkinter as tk
import threading
import time
from pynput.mouse import Button, Controller
from pynput.keyboard import Listener, KeyCode
press = "NO KEY SELECTED"

#ALLE DEFINITIONEN VON COMMANDS
#Clicker
def clicker():
    while True:
        if clicking:
            mouse.click(Button.left, 2)
        time.sleep(0.00001)

#EVENT
def toggle_event(key):
    if key == TOGGLE_KEY:
        global clicking
        clicking = not clicking

#Bot
def bot():
    global TOGGLE_KEY
    global clicking
    global mouse
    print(f"Drücke den Knopf. = '{press}'")
    TOGGLE_KEY = KeyCode(char=press)
    clicking = False
    mouse = Controller()
    click_thread = threading.Thread(target=clicker)
    click_thread.start()
    with Listener(on_press=toggle_event) as listener:
        listener.join()


#ACCEPT BUTTON NACH SETTINGS EINGABE
def settings_entry_accept_def():
    global press
    settings_entry.get()
    press = settings_entry.get().lower()
    settings_entry_accept.place_forget()
    settings_entry.place_forget()
    key_text.place_forget()
    text_settings.place(x=365, y=374)
    text_settings.configure(text="SAVED!", bg="grey5", fg="lightgreen")


#Einblenden von Entryfeld und Accept nach Klicken des Settingsbutton
def settings_button_def():
    settings_entry.place(x=349, y=377)
    settings_entry_accept.place(x=409, y=377)

#main Window einstellungen
main = tk.Tk()
main.geometry("500x400")
main.title("Auto-Clicker by Mork")
main.resizable(False, False)
main.config(bg="grey5")

#Titel
titel_text = tk.Label(main, text="Auto-Clicker",bg="grey5", fg="DARKRED", font=("Arial", 42))
titel_text.place(x=10,y=0)
titel_text_name = tk.Label(main, text="by Mork",bg="grey5", fg="DARKRED", font=("Arial", 26))
titel_text_name.place(x=190,y=70)

#Key to AutoClick
key_text = tk.Label(main, text=press, bg="grey5", fg="DARKRED")
key_text.place(x=345, y=313)

#TEXT UNTER SETTINGS
text_settings = tk.Label(main)

#SELECT KEY Button im Main Window
settings_button = tk.Button(main, text="KEY SELECT", bg="DARKRED", fg="LIGHTGREEN", width=10, height=2, font=("Arial", 10), command=settings_button_def)
settings_button.place(x=349, y=333)

#Entry Feld unter Settins Button
settings_entry = tk.Entry(main, bg="DARKRED", fg="LIGHTGREEN", width=9)


#Haken neben Entry Feld
settings_entry_accept = tk.Button(main, text="✔", bg="DARKRED", fg="LIGHTGREEN", width=4, height=1, command=settings_entry_accept_def)

#Start Button
start_button = tk.Button(main, text="Start Bot", bg="DARKRED", fg="LIGHTGREEN", width=10, height=2,font=("Arial", 10), command=bot)
start_button.place(x=78, y=333)

main.mainloop()

Re: TKINTER GUI Freeze

Verfasst: Freitag 16. August 2024, 15:04
von Sven_TKLOOP
Dein AutoClicker hat ein Problem, weil du das GUI-Event-Loop und den Clicker-Thread im selben Thread laufen lässt.
Das sorgt für einen Deadlock, weil der GUI-Thread auf den Clicker-Thread wartet und der Clicker-Thread auf Ereignisse aus dem GUI-Thread wartet.
Die Tkinter GUI und der Clicker müssen in separaten Threads laufen, um sich nicht gegenseitig zu blockieren.
Dein Listener für die Tasteneingaben blockiert den GUI-Thread, weil du ihn im Hauptthread startest. Du brauchst also einen separaten Thread für diesen Listener.

Den Clicker Thread solltest du auch als Daemon Thread starten damit dieser beendet wird wenn du die GUI schließt.

Du könntest eine angepasst funktion machen, so in der Art:

Code: Alles auswählen

def bot_thread():
    global TOGGLE_KEY
    global clicking
    global mouse
    TOGGLE_KEY = KeyCode(char=press)
    clicking = False
    mouse = Controller()
    click_thread = threading.Thread(target=clicker, daemon=True)
    click_thread.start()
    with Listener(on_press=toggle_event) as listener:
        listener.join()
Also einfach die Aufgaben auf Threads verteilen damit sich das Programm nicht selbst blockiert.