Hallo Profis,
ich weiß jetzt schon, dass dieser Thread sicherlich schon mehrfach erstellt wurde, habe ihn aber leider nicht gefunden (unterschiedliche Definitionen des Problems).
Ich schreibe gerade mein erstes Programm in Tkinter.
Ich habe schon die Canvas erstellt und auch schon Kreise an bestimmten Punkten "ausgegeben".
Mein Programm soll allerdings diesen Kreis (hängt von Radius r ab) alle 2 Sekunden aktualisieren. Das würde ich mit einer while-Schleife und time.sleep() realisieren.
Dennoch stell sich die Frage, wie kann ich die GUI verändern (alten Kreis löschen, neuen mit anderem Radius anzeigen), wenn bereits diese Tkinter.mainloop() ausgeführt wurde?
Hab mir schon diverses Zeug zu text updates durchgelesen, beidenen einfach der Text verändert wird, aber wie verändere ich einen Kreis?
Danke euch im vorraus für Antworten und Tipps.
Marc
Tkinter GUI aktualisieren
@M4rcde: Mit Schleife und `sleep()` geht das nicht weil die `mainloop()` ja schon läuft und auch laufen muss damit die GUI ordentlich dargestellt wird.
Du müsstest mit der `after()`-Methode auf Widgets arbeiten und immer wieder eine Funktion/Methode registrieren die in x Sekunden ausgeführt werden soll, dann kurz etwas macht, und die Kontrolle wieder an die GUI-Hauptschleife zurück gibt.
Löschen brauchst Du die Kreise nicht, wenn Du Dir die IDs merkst, kannst Du die Eigenschaften der Grafikelemente darüber später auch wieder ändern.
Du müsstest mit der `after()`-Methode auf Widgets arbeiten und immer wieder eine Funktion/Methode registrieren die in x Sekunden ausgeführt werden soll, dann kurz etwas macht, und die Kontrolle wieder an die GUI-Hauptschleife zurück gibt.
Löschen brauchst Du die Kreise nicht, wenn Du Dir die IDs merkst, kannst Du die Eigenschaften der Grafikelemente darüber später auch wieder ändern.
Gerade sieht der Code so aus:
Code: Alles auswählen
import Tkinter
import time
master = Tkinter.Tk()
canvas_width = 900
canvas_height = 400
w = Tkinter.Canvas(master,
width=canvas_width,
height=canvas_height)
def circle(canvas,x,y, r):
id = canvas.create_oval(x-r,y-r,x+r,y+r)
return id
circle(w,0,0, 50)
w.pack()
Tkinter.mainloop()
habe ich wie gesagt schon mehrfach durchsucht. Kann mit den Codes leider wenig anfangen und die entsprechen auch nicht den Anwendungszwecken von mir.
Da muss es doch ein ganz simples Review geben. Das ist doch was ganz simples... An dem Problem sitz ich den ganzen Tag...
Unglaublich, alles was ich probier klappt net...
Da muss es doch ein ganz simples Review geben. Das ist doch was ganz simples... An dem Problem sitz ich den ganzen Tag...
Unglaublich, alles was ich probier klappt net...
Hi M4rcde
Hier etwas zum ausprobieren mit 'widget.after()':Gruss wuf
Hier etwas zum ausprobieren mit 'widget.after()':
Code: Alles auswählen
import Tkinter as tk
CANVAS_WIDTH = 400
CANVAS_HEIGHT = 400
CIRCLE_XORG = 50
CIRCLE_YORG = 50
CIRCLE_RADIUS = 50
STEP_TIME = 30 # Milliseconds
XSTEP = 1
YSTEP = 1
def move_circle():
canvas.move("MyCircle", XSTEP, YSTEP)
x0, y0, x1, y1 = canvas.bbox("MyCircle")
if x1 > CANVAS_WIDTH: return
canvas.after(STEP_TIME, move_circle)
def circle(x, y, r):
canvas.create_oval(x-r, y-r, x+r, y+r, tag="MyCircle", fill='yellow')
master = tk.Tk()
master.title("Moving Circle")
master.geometry("+{}+{}".format(20,20))
canvas = tk.Canvas(master, width=CANVAS_WIDTH, height=CANVAS_HEIGHT)
canvas.pack()
circle(CIRCLE_XORG, CIRCLE_YORG, CIRCLE_RADIUS)
move_circle()
master.mainloop()
Take it easy Mates!
@wuf: Das mit den Tag finde ich ungünstig. Damit ist man entweder auf diesen einen Kreis beschränkt, beziehungsweise auf eine Gruppe von Kreisen die man immer zusammen ansprechen muss. Dann sollte das Tag 'MyCircles' heissen. Warum nicht einfach die ID des Kreises zurückgeben lassen statt ein Tag zu setzen?
Hi BlackJack
Da hast du natürlich recht. Mein Versuchsskript ist nur für ein Canvasobjekt "MyCircle" gedacht sonst ergibt sich für mehrere Canvasobjekte folgendes Verhalten:Für mehrere Canvasobjekte muss deren Tag erweitert werden.
Gruss wuf
Da hast du natürlich recht. Mein Versuchsskript ist nur für ein Canvasobjekt "MyCircle" gedacht sonst ergibt sich für mehrere Canvasobjekte folgendes Verhalten:
Code: Alles auswählen
import Tkinter as tk
CANVAS_WIDTH = 400
CANVAS_HEIGHT = 400
CIRCLE_XORG = 50
CIRCLE_YORG = 50
CIRCLE_RADIUS = 50
STEP_TIME = 30 # Milliseconds
XSTEP = 1
YSTEP = 1
def move_circle():
canvas.move("MyCircle", XSTEP, YSTEP)
x0, y0, x1, y1 = canvas.bbox("MyCircle")
if x1 > CANVAS_WIDTH: return
canvas.after(STEP_TIME, move_circle)
def circle(x, y, r):
canvas.create_oval(x-r, y-r, x+r, y+r, tag="MyCircle", fill='yellow')
master = tk.Tk()
master.title("Moving Circle")
master.geometry("+{}+{}".format(20,20))
canvas = tk.Canvas(master, width=CANVAS_WIDTH, height=CANVAS_HEIGHT)
canvas.pack()
circle(CIRCLE_XORG, CIRCLE_YORG, CIRCLE_RADIUS)
circle(CIRCLE_XORG+50, CIRCLE_YORG+50, CIRCLE_RADIUS)
move_circle()
master.mainloop()
Gruss wuf
Take it easy Mates!
@M4rcde: Die Funktion bei `after()` darf nicht lange laufen, wie jede Rückruffunktion bei GUIs weil die GUI-Hauptschleife laufen muss wenn die GUI nicht einfrieren soll.
Man muss die Schleifenschritte in Aufrufe umorganisieren, wie das Beispiel von wuf ja zeigt. Also keine Schleife in der der Kreis in jedem durchlauf bewegt/verändert wird, sondern ein Funktionsaufruf in dem das gemacht wird was sonst in einem Schleifendurchlauf passiert und diese funktion wird dann Regelmässig von der GUI aufgerufen wenn man sie immer wieder mit `after()` dazu bringt.
Man muss die Schleifenschritte in Aufrufe umorganisieren, wie das Beispiel von wuf ja zeigt. Also keine Schleife in der der Kreis in jedem durchlauf bewegt/verändert wird, sondern ein Funktionsaufruf in dem das gemacht wird was sonst in einem Schleifendurchlauf passiert und diese funktion wird dann Regelmässig von der GUI aufgerufen wenn man sie immer wieder mit `after()` dazu bringt.
Ich danke vielmals! Werde mich da wie gesagt nun mal einlesen Dankeschön!BlackJack hat geschrieben:@M4rcde: Die Funktion bei `after()` darf nicht lange laufen, wie jede Rückruffunktion bei GUIs weil die GUI-Hauptschleife laufen muss wenn die GUI nicht einfrieren soll.
Man muss die Schleifenschritte in Aufrufe umorganisieren, wie das Beispiel von wuf ja zeigt. Also keine Schleife in der der Kreis in jedem durchlauf bewegt/verändert wird, sondern ein Funktionsaufruf in dem das gemacht wird was sonst in einem Schleifendurchlauf passiert und diese funktion wird dann Regelmässig von der GUI aufgerufen wenn man sie immer wieder mit `after()` dazu bringt.