Python verlässt while-Schleife nicht

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Antworten
MissMillson
User
Beiträge: 3
Registriert: Donnerstag 15. Juni 2023, 16:12

Hallo zusammen,

ich habe vor ein paar Tagen angefangen, mich mit der Programmierung in Python (bzw. der Programmierung im Allgemeinen) zu beschäftigen, also bitte verzeiht mir meinen dilettantischen Code und mein Unwissen - aber ich bin ja hier, um zu lernen. :)

Ich versuche eine Anwendung zu programmieren, die meinen Screen wach hält (und ja, ich weiß, dass es hierfür bereits 1.000 Lösungen im Internet gibt, aber ich möchte verstehen, wieso meine nicht funktioniert :mrgreen: ).

Funktion sollte wie folgt sein:
Ich klicke den Start-Button und mein Cursor soll sich alle paar Sekunden bewegen. (-> funktioniert bis hierhin auch sehr gut)
Sobald ich dann den Button "Stopp" anklicke, soll das Programm stehenbleiben und quasi darauf warten, dass ich wieder den Start-Button anklicke.
Und hier liegt scheinbar das Problem:
Ich steige wie gewollt in die Schleife ein, komme dann allerdings nicht mehr raus. Sobald ich mit der linken Maustaste auch nur irgendwas anklicke, erhält das Programm keine Rückmeldung mehr.
Klicke ich dann aus dem Fenster raus, um z.B. etwas anderes zu machen, startet sich das Programm einfach wieder selbst.
Ich komme also nur raus, indem ich das Programm abschieße.

Lange Rede, kurzer Sinn:

hier mein Übungscode:

Code: Alles auswählen

import mouse
import time
import tkinter as tk

#actions are discribed here
def actionstartbutton():
    
    while mouse.is_pressed('left')is False:
        time.sleep(0.0050)
        mouse.move(960,540, absolute=True, duration=1)
        time.sleep(1)
        mouse.move(1000,540,absolute=True, duration=1)
        time.sleep(1)
        mouse.move(1000,600,absolute=True, duration=1)
        time.sleep(1)
        mouse.move(960,600,absolute=True, duration=1)
        time.sleep(3)

def actionstoppbutton():
    if mouse.is_pressed('left')is True:
        window.quit()
            

#GUI is discribed here
window = tk.Tk()

window.geometry('600x600')

window.configure(bg='#FFCC99')

frame = tk.Frame(window, bg='#EE959E')

startbutton = tk.Button(window, text='Start',
                        bg='#EE959E',
                        width='8',
                        height='1',
                        font=('Bernardo Moda Bold',20,'bold'),
                        command=actionstartbutton).pack(side='bottom')

stoppbutton = tk.Button(window, text='Stopp',
                        bg='#EE959E',
                        width='8',
                        height='1',
                        font=('Bernardo Moda Bold',20,'bold'),
                        command=actionstoppbutton).pack(side='bottom')

window.mainloop()
Sirius3
User
Beiträge: 17754
Registriert: Sonntag 21. Oktober 2012, 17:20

Der übliche Fehler, dass man bei GUIs keine lang laufenden Schleifen haben darf. Statt dessen läßt man via window.after immer wieder eine Funktion aufrufen, die die Maus ein kleines Stück weiter versetzt.
is-Vergleiche sind außer bei None meistens falsch. Bei `is True` läßt man das `is True` einfach weg, bei `is False` benutzt man `not`.
Du weist startbutton und stoppbutton auf komplizierte Weise None zu, benutzt die beiden Variablen auch nicht mehr, laß sie einfach weg.
Du erzeugst einen Frame, benutzt ihn aber nicht. Globale Variablen darf es nicht geben, alles was eine Funktion braucht, muß sie per Argument bekommen, wobei Du window.quit auch direkt als command angeben kannst.
Sirius3
User
Beiträge: 17754
Registriert: Sonntag 21. Oktober 2012, 17:20

Das ganze könnte ungefähr so aussehen:

Code: Alles auswählen

import mouse
import tkinter as tk
from functools import partial

CORNERS = [
    (960, 540, 1000),
    (1000,540, 1000),
    (1000,600, 1000),
    (960,600, 3005)
]

def move_step(window, corner_index, step_index, start_x, start_y):
    if mouse.is_pressed('left'):
        return
    x, y, delay = CORNERS[corner_index]
    if step_index == 120:
        window.after(delay, move_start, window, (corner_index + 1) % len(CORNERS))
    else:
        dx = x - start_x
        dy = y - start_y
        mouse.move(start_x + dx * step_index / 120, start_y + dy * step_index / 120) 
        window.after(1000 / 120, move_step, window, corner_index, step_index + 1, start_x, start_y)

def move_start(window, corner_index):
    start_x, start_y = mouse.get_position()
    move_step(window, corner_index, 0, start_x, start_y)

def actionstartbutton(window):
    window.after(5, move_start, window, 0) 

def main():
    window = tk.Tk()
    tk.Button(window, text='Start',
        command=partial(actionstartbutton, window
    ).pack(side='bottom')
    tk.Button(window, text='Stopp',
        command=window.quit
    ).pack(side='bottom')
    window.mainloop()

if __name__ == "__main__":
    main()
MissMillson
User
Beiträge: 3
Registriert: Donnerstag 15. Juni 2023, 16:12

Super, vielen Dank. Nachdem ich gestern der Verzweiflung nahe war, werde ich mir das gleich mal ansehen und hab jetzt zumindest verstanden, warum es nicht klappt.

Blöde Frage aber: ist es eine (ggf. auch ungeschriebene) Regel, dass GUIs keine lang laufenden Schleifen haben dürfen?

Und move_step könnte ich doch bestimmt auch über random lösen. 😊
__deets__
User
Beiträge: 14545
Registriert: Mittwoch 14. Oktober 2015, 14:29

Ja, das ist eine Regel. Die verhakten sich alle so. Es gibt andere Tools wie zb pygame, bei denen man eine Dauerschleife selbst betreibt. Und die sich darum für manche Anwendungszwecke, wie eben auch deinem, besser eignet.
MissMillson
User
Beiträge: 3
Registriert: Donnerstag 15. Juni 2023, 16:12

Verstehe - hätte ich das mal vorher gewusst. Aber durch Fehler lernt man ja angeblich am besten. 😅
Vielen Dank für eure Hilfe.
Antworten