Seite 1 von 1

Problem mit while-Schleife

Verfasst: Montag 30. August 2021, 12:43
von Eckes
Hallo Leute,

Ich möchte mir einen screen mit animierten Buchstaben basteln.
Es sollen einfach Buchstaben (Grafiken) im Bild hoch und runter laufen.
Folgendes Programm funktioniert aber nicht und ich finde den Grund nicht.

Wenn ich das über Pfeiltasten (mit bind) programmiere, läuft es, aber in einer Schleife hab ich nur noch einen weißen, eingefrorenen Bildschirm.


import time
from tkinter import *
from PIL import ImageTk, Image



main = Tk()
main.title("Test")
main.iconbitmap("prgpix/WindowIcon.ico")
main.geometry("1920x1200+0+0")
# main.wm_minsize(width=640, height=400) # wenn resizable = false, braucht man das hier ja nicht wirklich
main.resizable(width = False, height = False)
#main.configure(bg = "black")
hauptcanvas = Canvas(main, width = 1920, height = 1200, bd = 0, bg = "black", highlightthickness = 0)
hauptcanvas.place(x = 0, y = 0)


def startgedrueckt():
introscreen = False


introscreen = True


e1_pos = 200
c_pos = 250
k_pos = 300
e2_pos = 250
s_pos = 200

e1_pos_add = 1
c_pos_add = 1
k_pos_add = 1
e2_pos_add = 1
s_pos_add = 1

e_img = PhotoImage(file = "Stammtisch\Intro-E.png")
c_img = PhotoImage(file = "Stammtisch\Intro-C.png")
k_img = PhotoImage(file = "Stammtisch\Intro-K.png")
s_img = PhotoImage(file = "Stammtisch\Intro-S.png")

move_e1 = hauptcanvas.create_image(600, e1_pos, image=e_img, anchor="nw", tag="e1")
move_c = hauptcanvas.create_image(750, c_pos, image=c_img, anchor="nw", tag="c")
move_k = hauptcanvas.create_image(900, k_pos, image=k_img, anchor="nw", tag="k")
move_e2 = hauptcanvas.create_image(1050, e2_pos, image=e_img, anchor="nw", tag="e2")
move_s = hauptcanvas.create_image(1200, s_pos, image=s_img, anchor="nw", tag="s")

startbutton_img = ImageTk.PhotoImage(file="Stammtisch\STARTbutton.png")
startbutton = Button(hauptcanvas, borderwidth=0, bg="black", command=startgedrueckt)
startbutton.config(image=startbutton_img, activebackground="black")
startbutton.place(x=830, y=990)

def ani():
global e1_pos, c_pos, k_pos, e2_pos, s_pos, e1_pos_add, c_pos_add, k_pos_add, e2_pos_add, s_pos_add

e1_pos += e1_pos_add
c_pos += c_pos_add
k_pos += k_pos_add
e2_pos += e2_pos_add
s_pos += s_pos_add


print (e1_pos)


if e1_pos > 700:
e1_pos_add = -1
if c_pos > 700:
c_pos_add = -1
if k_pos > 700:
k_pos_add = -1
if e2_pos > 700:
e2_pos_add = -1
if s_pos > 700:
s_pos_add = -1

if e1_pos < 100:
e1_pos_add = 1
if c_pos < 100:
c_pos_add = 1
if k_pos < 100:
k_pos_add = 1
if e2_pos < 100:
e2_pos_add = 1
if s_pos < 100:
s_pos_add = 1

hauptcanvas.move(move_e1, 0, e1_pos_add)
hauptcanvas.move(move_c, 0, e1_pos_add)
hauptcanvas.move(move_k, 0, e1_pos_add)
hauptcanvas.move(move_e2, 0, e1_pos_add)
hauptcanvas.move(move_s, 0, e1_pos_add)




while introscreen:
ani()
#clock.tick(40)
time.sleep(0.1)

Re: Problem mit while-Schleife

Verfasst: Montag 30. August 2021, 13:04
von Sirius3
So funktionieren GUIs nicht; GUIs sind ereignisgesteuert, lang laufende Schleifen darf es nicht geben. Bei Dir löst man das mit `after`.

Daneben solltest Du keine *-Importe benutzen und kein `global`. Variablen. Variablennamen müssen aussagekräftig sein.
Statt jeweils fünf mal den selben Code für jeden Buchstaben würde man eine Buchstabenklasse definieren.

Code: Alles auswählen

import tkinter as tk
from PIL import ImageTk, Image

class Character:
    def __init__(self, canvas, x_position, y_position, filename):
        self.y_position = y_position
        self.canvas = canvas
        self.image = ImageTk.PhotoImage(file=filename)
        self.canvas_id = canvas.create_image(x_position, e1_pos, image=self.image, anchor="nw")
        self.direction = 1
    
    def move(self):
        self.canvas.move(self.canvas_id, 0, self.direction)
        self.y_position += self.direction
        if self.y_position > 700:
            self.direction = -1
        elif self.y_position < 100:
            self.direction = 1


def animation(root, characters):
    for character in characters:
        character.move()
    root.after(100, animation, root, characters)

def main():
    root = tk.Tk()
    root.title("Test")
    root.iconbitmap("prgpix/WindowIcon.ico")
    root.resizable(width=False, height=False)
    canvas = tk.Canvas(root, width=1920, height=1200, bd=0, bg="black", highlightthickness=0)
    canvas.pack()
    buchstaben = [
        Character(canvas, 600, 200, "Stammtisch/Intro-E.png"),
        Character(canvas, 750, 250, "Stammtisch/Intro-C.png"),
        Character(canvas, 900, 300, "Stammtisch/Intro-K.png"),
        Character(canvas, 1050, 250, "Stammtisch/Intro-E.png"),
        Character(canvas, 1200, 200, "Stammtisch/Intro-S.png"),
    ]

    startbutton_img = ImageTk.PhotoImage(file="Stammtisch/STARTbutton.png")
    startbutton = tk.Button(canvas, borderwidth=0, bg="black")
    startbutton.config(image=startbutton_img, activebackground="black")
    startbutton.place(x=830, y=990)
    animation(root, characters)
    root.mainloop()

if __name__ == "__main__":
    main()

Re: Problem mit while-Schleife

Verfasst: Montag 30. August 2021, 13:25
von Eckes
Hab es jetzt auch mal so probiert - das läuft auch (hab das so gemacht, weil ich wollte, daß die Buchstaben unterschiedlich "hüpfen"):


import time
from tkinter import *
from PIL import ImageTk, Image



main = Tk()
main.title("Test")
main.iconbitmap("prgpix/WindowIcon.ico")
main.geometry("1920x1200+0+0")
# main.wm_minsize(width=640, height=400) # wenn resizable = false, braucht man das hier ja nicht wirklich
main.resizable(width = False, height = False)
#main.configure(bg = "black")
hauptcanvas = Canvas(main, width = 1920, height = 1200, bd = 0, bg = "black", highlightthickness = 0)
hauptcanvas.place(x = 0, y = 0)


def startgedrueckt():
introscreen = False


introscreen = True


e1_pos = 200
c_pos = 250
k_pos = 300
e2_pos = 250
s_pos = 200

e1_pos_add = 1.1
c_pos_add = 0.9
k_pos_add = 1.3
e2_pos_add = 0.7
s_pos_add = 1.4

e_img = PhotoImage(file = "Stammtisch\Intro-E.png")
c_img = PhotoImage(file = "Stammtisch\Intro-C.png")
k_img = PhotoImage(file = "Stammtisch\Intro-K.png")
s_img = PhotoImage(file = "Stammtisch\Intro-S.png")

move_e1 = hauptcanvas.create_image(600, e1_pos, image=e_img, anchor="nw")
move_c = hauptcanvas.create_image(750, c_pos, image=c_img, anchor="nw")
move_k = hauptcanvas.create_image(900, k_pos, image=k_img, anchor="nw")
move_e2 = hauptcanvas.create_image(1050, e2_pos, image=e_img, anchor="nw")
move_s = hauptcanvas.create_image(1200, s_pos, image=s_img, anchor="nw")

startbutton_img = ImageTk.PhotoImage(file="Stammtisch\STARTbutton.png")
startbutton = Button(hauptcanvas, borderwidth=0, bg="black", command=startgedrueckt)
startbutton.config(image=startbutton_img, activebackground="black")
startbutton.place(x=830, y=990)

def ani():
global e1_pos, c_pos, k_pos, e2_pos, s_pos, e1_pos_add, c_pos_add, k_pos_add, e2_pos_add, s_pos_add

e1_pos += e1_pos_add
c_pos += c_pos_add
k_pos += k_pos_add
e2_pos += e2_pos_add
s_pos += s_pos_add

print (e1_pos)


if e1_pos > 500:
e1_pos_add = -1.1
if c_pos > 500:
c_pos_add = -0.9
if k_pos > 500:
k_pos_add = -1.3
if e2_pos > 500:
e2_pos_add = -0.7
if s_pos > 500:
s_pos_add = -1.4

if e1_pos < 100:
e1_pos_add = 1.1
if c_pos < 100:
c_pos_add = 0.9
if k_pos < 100:
k_pos_add = 1.3
if e2_pos < 100:
e2_pos_add = 0.7
if s_pos < 100:
s_pos_add = 1.4

hauptcanvas.move(move_e1, 0, e1_pos_add)
hauptcanvas.move(move_c, 0, c_pos_add)
hauptcanvas.move(move_k, 0, k_pos_add)
hauptcanvas.move(move_e2, 0, e2_pos_add)
hauptcanvas.move(move_s, 0, s_pos_add)

main.after(1, ani)

Re: Problem mit while-Schleife

Verfasst: Montag 30. August 2021, 13:34
von Eckes
warum keine *-importe benutzen ?

Re: Problem mit while-Schleife

Verfasst: Montag 30. August 2021, 13:43
von __deets__
Weil die verschleiern, woher ein Name kommt. Und gerade bei tkinter sind das mal so eben 200, die plötzlich in deinem Namensraum auftauchen. Inklusive so Dinge wie „END“, was man vielleicht auch mal anders definieren will.

Re: Problem mit while-Schleife

Verfasst: Montag 30. August 2021, 13:52
von Eckes
ah ja - das stimmt natürlich.
Hab jetzt die Werte nochmal bisschen verändert und es sieht ganz lustig aus. Ich bin ja nicht der mega-Programmierer, aber Python macht irgendwie spaß.
In meinem Alter (ü50) werd' ich wohl keine großen Sachen mehr schaffen, aber es hält zumindest geistig etwas fit denke.

Vielen Dank !

Re: Problem mit while-Schleife

Verfasst: Montag 30. August 2021, 14:22
von Sirius3
@Eckes: auch wenn die Buchstaben jetzt unterschiedlich schnell hüpfen, schreibt man dafür immer noch eine Klasse, halt mit zusätzlichem Geschwindigkeits-Parameter.

Re: Problem mit while-Schleife

Verfasst: Montag 30. August 2021, 15:14
von Eckes
okay - dann will ich mich mal dran versuchen :-)

Re: Problem mit while-Schleife

Verfasst: Dienstag 31. August 2021, 08:59
von Eckes
Jetzt aber zum Problem mit der While-Schleife:

wenn man beispielsweise ein Game schreiben will, was ein Intro, einen Hauptteil und eine Ende hat, man aber keine While-Schleife zum Aufrufen der einzelnen Teile nutzen darf, wie kann man das dann realisieren ?

Mein Plan war ja in etwa so:

def intro():
code

def game():
code

def ende():
code

run = True
i = True
g = False
e = False

while run:
if i:
intro()
if g:
game()
if e:
ende():

aber das geht ja nicht wegen dem while.

wie also kann man das intro laufen lassen und die anderen sachen noch nicht und wie dann das intro beenden und das game starten ?

Re: Problem mit while-Schleife

Verfasst: Dienstag 31. August 2021, 09:42
von Sirius3
Genau, so geht das nicht. Spiele laufen ja meist nur in einem Fenster ab. Das heißt, für Intro, Game und Ende hast Du jeweils einen eigenen Frame, den Du einfach im Hauptfenster austauschen kannst. Also Du startest mit Intro, beim Drücken eines Knopfes wird der Intro-Frame aus dem Hauptfenster gelöscht und statt dessen der Game-Frame erzeugt und dargestellt.
Am besten schreibst Du für jeden der drei Teile jeweils eine Klasse, die von Frame erbt. Dann kannst Du das von der Hauptfensterklasse aus einfach steuern.

Code: Alles auswählen

import tkinter as tk

class Intro(tk.Frame):
    def __init__(self, parent):
        tk.Frame.__init__(self, parent)
        self.parent = parent
        tk.Label(self, text="Intro").pack()
        tk.Button(self, text="Weiter", command=parent.start_game).pack()

class Game(tk.Frame):
    def __init__(self, parent):
        tk.Frame.__init__(self, parent)
        self.parent = parent
        tk.Label(self, text="Game").pack()
        tk.Button(self, text="Ende", command=parent.end_game).pack()


class MainWindow(tk.Tk):
    def __init__(self):
        tk.Tk.__init__(self)
        self.current_frame = Intro(self)
        self.current_frame.pack()
    
    def start_game(self):
        self.current_frame.pack_forget()
        self.current_frame = Game(self)
        self.current_frame.pack()
        
    def end_game(self):
        self.destroy()


def main()
    root = MainWindow()
    root.mainloop()

if __name__ == "__main__":
    main()

Re: Problem mit while-Schleife

Verfasst: Samstag 9. Oktober 2021, 07:13
von Eckes
Das kann ich aber doch sicher auch auf mehrere Dateien verteilen, damit der Code nicht zu lang wird für jeden Teil ?

also müsste ich dann am Anfang

import Intro
import Game

machen ?

Re: Problem mit while-Schleife

Verfasst: Samstag 9. Oktober 2021, 09:35
von Sirius3
Man teilt ein Programm so in Module auf, dass jedes Modul eine fachliche Einheit bildet.
Die Teile eines Programms packst Du in ein Package. Module schreibt man, wie Funktionen und Variablen auch, komplett klein.

Code: Alles auswählen

from das_tolle_spiel.intro import Intro