Tkinter GUI hangs when loop

Asked

Viewed 781 times

1

I am new to programming and have faced some difficulties to execute the code perfectly.

I chose python for its flexibility.

For some time I have been trying to create a macro with GUI, I use Tkinter, the window is the way I planned, and the macro commands too. But when I press the button to turn on the macro, the window hangs and stops responding, I can’t click the button again to turn off the macro or anything like that, but I notice that the macro is still running perfectly.

I’m counting on your help to fix this lock on Tkinter’s window. Here is my code.

from Tkinter import *
import ctypes
import time


class Janela:

    def __init__(self, toplevel):

        self.primeira = Frame(toplevel)
        self.primeira.pack()
        self.segunda = Frame(toplevel, pady=10)
        self.segunda.pack()
        self.terceira = Frame(toplevel,)
        self.terceira.pack()

        self.title = Label(self.primeira, text='"Perera" Trainer', font=('Verdana', '13', 'bold'))
        self.title['width'] = 20
        self.title['height'] = 5
        self.title.pack()

        self.nome = Label(self.segunda, text='Hotkey da spell: ', font=('Verdana', '12',), width=13).pack(side=LEFT)

        self.hotkey = Entry(self.segunda, width=2, font=('Verdana', '12', 'bold'))
        self.hotkey.focus_force()
        self.hotkey.pack(side=LEFT)

        Label(self.terceira, text='Ligar Trainer', font=('Arial', '12', 'bold'), height=3,).pack()

        self.botao = Button(self.terceira, font=('Arial', '13', 'bold'), text='ON', bg='gray')
        self.botao.bind("<Button-1>", self.ligar)
        self.botao.pack()

    def ligar(self, event):
        if self.botao['bg'] == 'gray':
            self.botao['bg'] = 'deepskyblue'
        else:
            self.botao['bg'] = 'gray'

        VAR = self.hotkey.get()
        self.hot = int(VAR[1])

        while self.botao['bg'] == 'deepskyblue':
            time.sleep(2)
            if self.hot == 1:
                ctypes.windll.user32.keybd_event(0x70, 0, 0, 0)
                ctypes.windll.user32.keybd_event(0x70, 0, 0x0002, 0)
            elif self.hot == 2:
                ctypes.windll.user32.keybd_event(0x71, 0, 0, 0)
                ctypes.windll.user32.keybd_event(0x71, 0, 0x0002, 0)
            elif self.hot == 3:
                ctypes.windll.user32.keybd_event(0x72, 0, 0, 0)
                ctypes.windll.user32.keybd_event(0x72, 0, 0x0002, 0)
            elif self.hot == 4:
                ctypes.windll.user32.keybd_event(0x73, 0, 0, 0)
                ctypes.windll.user32.keybd_event(0x73, 0, 0x0002, 0)
            elif self.hot == 5:
                ctypes.windll.user32.keybd_event(0x74, 0, 0, 0)
                ctypes.windll.user32.keybd_event(0x74, 0, 0x0002, 0)
            elif self.hot == 6:
                ctypes.windll.user32.keybd_event(0x75, 0, 0, 0)
                ctypes.windll.user32.keybd_event(0x75, 0, 0x0002, 0)
            elif self.hot == 7:
                ctypes.windll.user32.keybd_event(0x76, 0, 0, 0)
                ctypes.windll.user32.keybd_event(0x76, 0, 0x0002, 0)
            elif self.hot == 8:
                ctypes.windll.user32.keybd_event(0x77, 0, 0, 0)
                ctypes.windll.user32.keybd_event(0x77, 0, 0x0002, 0)
            elif self.hot == 9:
                ctypes.windll.user32.keybd_event(0x78, 0, 0, 0)
                ctypes.windll.user32.keybd_event(0x78, 0, 0x0002, 0)
            elif self.hot == 10:
                ctypes.windll.user32.keybd_event(0x79, 0, 0, 0)
                ctypes.windll.user32.keybd_event(0x79, 0, 0x0002, 0)
            elif self.hot == 11:
                ctypes.windll.user32.keybd_event(0x7A, 0, 0, 0)
                ctypes.windll.user32.keybd_event(0x7A, 0, 0x0002, 0)
            elif self.hot == 12:
                ctypes.windll.user32.keybd_event(0x7B, 0, 0, 0)
                ctypes.windll.user32.keybd_event(0x7B, 0, 0x0002, 0)

            time.sleep(2)
            ctypes.windll.user32.mouse_event(0x8, 0, 0, 0, 0)
            ctypes.windll.user32.mouse_event(0x10, 0, 0, 0, 0)
            time.sleep(2)

            ctypes.windll.user32.keybd_event(0xA2, 0, 0, 0)
            ctypes.windll.user32.keybd_event(0x25, 0, 0, 0)
            ctypes.windll.user32.keybd_event(0x25, 0, 0x0002, 0)
            ctypes.windll.user32.keybd_event(0xA2, 0, 0x0002, 0)
            time.sleep(0.2)
            ctypes.windll.user32.keybd_event(0xA2, 0, 0, 0)
            ctypes.windll.user32.keybd_event(0x26, 0, 0, 0)
            ctypes.windll.user32.keybd_event(0x26, 0, 0x0002, 0)
            ctypes.windll.user32.keybd_event(0xA2, 0, 0x0002, 0)
            time.sleep(0.2)
            ctypes.windll.user32.keybd_event(0xA2, 0, 0, 0)
            ctypes.windll.user32.keybd_event(0x27, 0, 0, 0)
            ctypes.windll.user32.keybd_event(0x27, 0, 0x0002, 0)
            ctypes.windll.user32.keybd_event(0xA2, 0, 0x0002, 0)
            time.sleep(0.2)
            ctypes.windll.user32.keybd_event(0xA2, 0, 0, 0)
            ctypes.windll.user32.keybd_event(0x28, 0, 0, 0)
            ctypes.windll.user32.keybd_event(0x28, 0, 0x0002, 0)
            ctypes.windll.user32.keybd_event(0xA2, 0, 0x0002, 0)


raiz = Tk()
Janela(raiz)
raiz.mainloop()

1 answer

0


Your first problem is the fact that you wear time.sleep, and the second is to use the while loop. When you use the function time.sleep blocks the mainloop of the object Tk that you created. The same happens if you have a loop (that lasts a while), or an operation that lasts a lot. Here’s a tutorial if you want to know more about it and what are some possible solutions.

https://github.com/dossan/tkinter/blob/master/other/tutorials/why_your_GUI_freezes.md

Not without what you want to create (and for what) with this program, but a solution would be to use the function after of any Tkinter widget (or better any widget has this function because it inherits it from Widget mother or father) This function theoretically does not locate the interface, and allows you to schedule the execution of a piece of code between a certain time you specify in milliseconds.

Here you have your program modified but using the function after. If you don’t understand something, ask.

from Tkinter import *
import ctypes
import time


class Janela:

    def __init__(self, toplevel):
        self.primeira = Frame(toplevel)
        self.primeira.pack()
        self.segunda = Frame(toplevel, pady=10)
        self.segunda.pack()
        self.terceira = Frame(toplevel,)
        self.terceira.pack()

        self.title = Label(self.primeira, text='"Perera" Trainer', font=('Verdana', '13', 'bold'))
        self.title['width'] = 20
        self.title['height'] = 5
        self.title.pack()

        self.nome = Label(self.segunda, text='Hotkey da spell: ', font=('Verdana', '12',), width=13).pack(side=LEFT)

        self.hotkey = Entry(self.segunda, width=2, font=('Verdana', '12', 'bold'))
        self.hotkey.focus_force()
        self.hotkey.pack(side=LEFT)

        Label(self.terceira, text='Ligar Trainer', font=('Arial', '12', 'bold'), height=3,).pack()

        self.botao = Button(self.terceira, font=('Arial', '13', 'bold'), text='ON', bg='gray')
        self.botao.bind("<Button-1>", self.ligar)
        self.botao.pack()

    def callback1(self):
        print "callback 1" 

        if self.hot == 1:
            ctypes.windll.user32.keybd_event(0x70, 0, 0, 0)
            ctypes.windll.user32.keybd_event(0x70, 0, 0x0002, 0)
        elif self.hot == 2:
            ctypes.windll.user32.keybd_event(0x71, 0, 0, 0)
            ctypes.windll.user32.keybd_event(0x71, 0, 0x0002, 0)
        elif self.hot == 3:
            ctypes.windll.user32.keybd_event(0x72, 0, 0, 0)
            ctypes.windll.user32.keybd_event(0x72, 0, 0x0002, 0)
        elif self.hot == 4:
            ctypes.windll.user32.keybd_event(0x73, 0, 0, 0)
            ctypes.windll.user32.keybd_event(0x73, 0, 0x0002, 0)
        elif self.hot == 5:
            ctypes.windll.user32.keybd_event(0x74, 0, 0, 0)
            ctypes.windll.user32.keybd_event(0x74, 0, 0x0002, 0)
        elif self.hot == 6:
            ctypes.windll.user32.keybd_event(0x75, 0, 0, 0)
            ctypes.windll.user32.keybd_event(0x75, 0, 0x0002, 0)
        elif self.hot == 7:
            ctypes.windll.user32.keybd_event(0x76, 0, 0, 0)
            ctypes.windll.user32.keybd_event(0x76, 0, 0x0002, 0)
        elif self.hot == 8:
            ctypes.windll.user32.keybd_event(0x77, 0, 0, 0)
            ctypes.windll.user32.keybd_event(0x77, 0, 0x0002, 0)
        elif self.hot == 9:
            ctypes.windll.user32.keybd_event(0x78, 0, 0, 0)
            ctypes.windll.user32.keybd_event(0x78, 0, 0x0002, 0)
        elif self.hot == 10:
            ctypes.windll.user32.keybd_event(0x79, 0, 0, 0)
            ctypes.windll.user32.keybd_event(0x79, 0, 0x0002, 0)
        elif self.hot == 11:
            ctypes.windll.user32.keybd_event(0x7A, 0, 0, 0)
            ctypes.windll.user32.keybd_event(0x7A, 0, 0x0002, 0)
        elif self.hot == 12:
            ctypes.windll.user32.keybd_event(0x7B, 0, 0, 0)
            ctypes.windll.user32.keybd_event(0x7B, 0, 0x0002, 0)

        self.primeira.after(2000, self.callback2)

    def callback2(self):
        print "callback 2"         
        ctypes.windll.user32.mouse_event(0x8, 0, 0, 0, 0)
        ctypes.windll.user32.mouse_event(0x10, 0, 0, 0, 0)
        self.primeira.after(2000, self.callback3)

    def callback3(self):
        print "callback 3"           
        ctypes.windll.user32.keybd_event(0xA2, 0, 0, 0)
        ctypes.windll.user32.keybd_event(0x25, 0, 0, 0)
        ctypes.windll.user32.keybd_event(0x25, 0, 0x0002, 0)
        ctypes.windll.user32.keybd_event(0xA2, 0, 0x0002, 0)
        self.primeira.after(200, self.callback4)

    def callback4(self):
        print "callback 4"           
        ctypes.windll.user32.keybd_event(0xA2, 0, 0, 0)
        ctypes.windll.user32.keybd_event(0x26, 0, 0, 0)
        ctypes.windll.user32.keybd_event(0x26, 0, 0x0002, 0)
        ctypes.windll.user32.keybd_event(0xA2, 0, 0x0002, 0)
        self.primeira.after(200, self.callback5)

    def callback5(self):
        print "callback 5"                   
        ctypes.windll.user32.keybd_event(0xA2, 0, 0, 0)
        ctypes.windll.user32.keybd_event(0x27, 0, 0, 0)
        ctypes.windll.user32.keybd_event(0x27, 0, 0x0002, 0)
        ctypes.windll.user32.keybd_event(0xA2, 0, 0x0002, 0)
        self.primeira.after(200, self.callback6)

    def callback6(self):
        print "callback 6"                   
        ctypes.windll.user32.keybd_event(0xA2, 0, 0, 0)
        ctypes.windll.user32.keybd_event(0x28, 0, 0, 0)
        ctypes.windll.user32.keybd_event(0x28, 0, 0x0002, 0)
        ctypes.windll.user32.keybd_event(0xA2, 0, 0x0002, 0)

        if self.botao['bg'] == 'deepskyblue':
            self.primeira.after(200, self.callback1)

    def ligar(self, event):
        if self.botao['bg'] == 'gray':
            self.botao['bg'] = 'deepskyblue'
        else:
            self.botao['bg'] = 'gray'

        VAR = self.hotkey.get()

        self.hot = int(VAR)

        if self.botao['bg'] == 'deepskyblue':
            self.primeira.after(2000, self.callback1)


raiz = Tk()
Janela(raiz)
raiz.mainloop()

Note that I no longer use the while loop more yes a if with the possibility to reschedule a call to function (or callback, as it is said in English) callback1, the first that is called with all ifs.

  • After a few editions of this code I managed to get where I wanted. You just forgot to assign [1] after the VAR, it would be " self.hot = int(VAR[1]) ". Still, thank you very much.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.