Seite 1 von 1
Tkinter-Rechteckobjekte mittels for-Schleife erstellen
Verfasst: Dienstag 3. Juli 2018, 21:58
von Atalanttore
Hallo
Ich würde gerne Tkinter-Rechteckobjekte mittels for-Schleife erstellen und den Zähler der for-Schleife für die Benennung der Rechteckobjekte und außerdem als Multiplikator für die Position/Größe der Rechtecke verwenden. Mit Google komme ich da nicht weiter.
Mein aktueller Code sieht so aus:
Code: Alles auswählen
import tkinter as tk
x1 = 50
y1 = 0
x2 = 150
y2 = 50
class Application:
def __init__(self, app_win):
self.app_win = app_win
self.width = app_win.winfo_screenwidth()
self.height = app_win.winfo_screenheight()
self.center_x = self.width / 2
self.center_y = self.height / 2
self.window = tk.Canvas(app_win, width=self.width, height=self.height,
bg='black')
self.window.pack()
class Rectangle():
def __init__(self, app_win, x1, y1, x2, y2):
self.app_win = app_win
self.x1 = x1
self.y1 = y1
self.x2 = x2
self.y2 = y2
self.rectangle = self.window.create_rectangle(self.x1, self.y1, self.x2, self.y2, # Problem 1
fill='red')
self.window.pack()
def main():
app_win = tk.Tk()
app_win.attributes("-fullscreen", True)
app_win.bind("<Escape>", lambda e: app_win.quit())
app = Application(app_win)
rectangle_list = []
for i in range(0,5):
rectangle{i} = Rectangle(app_win, x1*i, y1, x2*i, y2*i) # Problem 2
rectangle_list.append(rectangle{i})
app_win.mainloop()
if __name__ == '__main__':
main()
- Das erste Problem ist, dass ich nicht in Erfahrung bringen konnte, wie ich der Klasse `Rectangle` den Canvas `window` des Objekts `app` übergeben kann.
- Das zweite Problem ist dann die Erzeugung der Rechteckobjekte mittels for-Schleife und deren Speicherung in einer Liste.
- Enthält mein Code noch weitere Probleme?
Gruß
Atalanttore
Re: Tkinter-Rechteckobjekte mittels for-Schleife erstellen
Verfasst: Dienstag 3. Juli 2018, 22:29
von __deets__
Das mit dem {i} ist Murks und kann ersatzlos gestrichen werden. Was du im Rectangle window nennst ist ein Cnavas, und sollte auch so heißen. Und dann muss es auch ein canvas sein, den du erzeugst. Und darauf für jedes Rechteck pack aufzurufen ist bestenfalls überflüssig, schlimmstenfalls ein Bug. Da machst du an der Stelle wo du den Canvas erzeugst genau ein mal. Du hat’s doch Code von wuf bekommen, der einen canvas erzeugt? Wo ist das denn alles hin?
Re: Tkinter-Rechteckobjekte mittels for-Schleife erstellen
Verfasst: Dienstag 3. Juli 2018, 22:34
von __blackjack__
@Atalanttore: 1. Der `Canvas` ist als Attribut auf Deinem `Application`-Objekt. Den kannst Du da ganz normal per ``.``-Operator abgfragen.
2. Dieses {i} nach einem Namen ist kein gülitiges. Wenn Du das an beiden Stellen einfach entfernst, funktionierts.
3. Grunddatentypen gehören nicht in Namen. Also `rectangles` statt `rectangle_list`. Während der Entwicklung kommt es häufiger vor das man mal Datentypen durch passendere ersetzt und dann hat man entweder irreführende falsche Namen im Programm, oder muss das ganze Programm durchgehen und die anpassen.
Die letzte Zeile in `Rectangle.__init__()` würde nicht einmal Sinn machen wenn es `self.window` geben würde. Das `Canvas`-Objekt ist ja bereits angezeigt.
Wozu muss ein `Rectangle` das Hauptfenster kennen?
Re: Tkinter-Rechteckobjekte mittels for-Schleife erstellen
Verfasst: Dienstag 3. Juli 2018, 23:26
von wuf
Hi Atalanttore
Hier zur Klärung wieder etwas Code:
Code: Alles auswählen
import tkinter as tk
class Application:
def __init__(self, app_win):
self.app_win = app_win
self.width = app_win.winfo_screenwidth()
self.height = app_win.winfo_screenheight()
self.center_x = self.width / 2
self.center_y = self.height / 2
self.canvas = tk.Canvas(app_win, width=self.width, height=self.height,
highlightthickness=0, bg='black')
self.canvas.pack()
self.rectangles = []
x1 = 50
y1 = 50
x2 = 150
y2 = 100
for nr in range(5):
rectangle = self.canvas.create_rectangle(
x1*nr, y1*nr, x2*nr,y2*nr, fill='red')
self.rectangles.append(rectangle)
def main():
app_win = tk.Tk()
app_win.attributes("-fullscreen", True)
app_win.bind("<Escape>", lambda e: app_win.quit())
app = Application(app_win)
app_win.mainloop()
if __name__ == '__main__':
main()
Gruss wuf
Re: Tkinter-Rechteckobjekte mittels for-Schleife erstellen
Verfasst: Mittwoch 4. Juli 2018, 08:06
von __deets__
Ich hab nich prompt verlesen weil,alles window heißt, auch wenn es Canvas ist. Den Teil meiner Bemerkung kannst du also ignorieren. Nur musst du eben den Canvas reinreichen.
Re: Tkinter-Rechteckobjekte mittels for-Schleife erstellen
Verfasst: Sonntag 8. Juli 2018, 20:13
von Atalanttore
Danke für die Erklärungen. Eine Kombination aus Buchstaben und einer fortlaufenden Zahl als Objektname funktioniert dann wohl nicht.
@wuf: Danke für den Code. Ich habe die Klasse `Application` noch um folgende Methode zum Ändern der Füllfarbe erweitert.
Code: Alles auswählen
def change_color(self, number, color):
self.canvas.itemconfig(self.rectangles[number], fill=color)
Gruß
Atalanttore
Re: Tkinter-Rechteckobjekte mittels for-Schleife erstellen
Verfasst: Sonntag 8. Juli 2018, 20:36
von __blackjack__
@Atalanttore: Die Kombination aus Buchstaben und einer fortlaufenden Zahl als Objektname ist eine Liste. Die hat einen Namen und die Objekte sind über eine fortlaufende Nummer über den Namen und den Indexoperator ansprechbar. Wobei man das eher selten braucht, weil der Index für eine Schleife über die Objekte ja beispielsweise nicht nötig ist.
Re: Tkinter-Rechteckobjekte mittels for-Schleife erstellen
Verfasst: Montag 9. Juli 2018, 21:42
von Atalanttore
@__blackjack__: Mit einer Kombination aus Buchstaben und einer fortlaufenden Zahl als Objektname habe ich gemeint, dass am Ende so eine Liste mit Objekten entsteht:
Code: Alles auswählen
rectangles = [rectangle_1, rectangle_2, rectangle_3, rectangle_4, rectangle_5, rectangle_6, rectangle_7, rectangle_8, rectangle_9, rectangle_10]
Aber eigentlich ist das auch gar nicht so wichtig, weil bei einer Schleife über die Objekte in der Liste die Objektnamen keine Rolle spielen.
Ich habe nun mit einer for-Schleife versucht die Füllfarbe der Rechteckobjekte in der Liste nacheinander mit jeweils 1 Sekunde Verzögerung auf grün zu ändern. Leider klappt das nicht nacheinander, sondern nach 1 Sekunde Verzögerung wird die Farbe aller Rechtecke in grün geändert.
Ich habe den Verdacht, dass die for-Schleife die Anweisung `app_win.after(1000, app.change_color, i, 'green')` ohne nennenswerte Verzögerung 10 mal nacheinander aufruft und deshalb nach 1 Sekunde die 10 Methoden `app.change_color(i, 'green')` der einzelnen Rechteckobjekte gleichzeitig aufgerufen werden.
Der Code sieht so aus:
Code: Alles auswählen
import tkinter as tk
class Application:
def __init__(self, app_win):
self.app_win = app_win
self.width = app_win.winfo_screenwidth()
self.height = app_win.winfo_screenheight()
self.center_x = self.width / 2
self.center_y = self.height / 2
self.canvas = tk.Canvas(app_win, width=self.width, height=self.height,
highlightthickness=0, bg='black')
self.canvas.pack()
self.rectangles = []
x1 = 50
y1 = 50
x2 = 150
y2 = 100
for nr in range(10):
rectangle = self.canvas.create_rectangle(
x1 * nr, y1 * nr, x2 * nr, y2 * nr, fill='red')
self.rectangles.append(rectangle)
def change_color(self, number, color):
self.canvas.itemconfig(self.rectangles[number], fill=color)
def main():
app_win = tk.Tk()
app_win.attributes("-fullscreen", True)
app_win.bind("<Escape>", lambda e: app_win.quit())
app = Application(app_win)
for i in app.rectangles: # Funktioniert
app_win.after(1000, app.change_color, i, 'green') # so nicht
app_win.mainloop()
if __name__ == '__main__':
main()
Gruß
Atalanttore
Re: Tkinter-Rechteckobjekte mittels for-Schleife erstellen
Verfasst: Montag 9. Juli 2018, 22:10
von Sirius3
`i` ist auch ein schlechter Name für eine Canvas-ID, die auch nicht als Index in die rectangles-Liste taugt. Wenn Du jedes Rechteck mit 1 Sekunde abstand umschalten willst, dann muß das erste change_color nach 1000 ms, das zweite nach 2000 ms usw. aufgerufen werden.
Re: Tkinter-Rechteckobjekte mittels for-Schleife erstellen
Verfasst: Montag 9. Juli 2018, 23:02
von wuf
Hi Atalanttore
Hier eine mögliche Lösungsvariante:
Code: Alles auswählen
import tkinter as tk
class Application:
def __init__(self, app_win):
self.app_win = app_win
self.width = app_win.winfo_screenwidth()
self.height = app_win.winfo_screenheight()
self.center_x = self.width / 2
self.center_y = self.height / 2
self.canvas = tk.Canvas(app_win, width=self.width, height=self.height,
highlightthickness=0, bg='black')
self.canvas.pack()
self.rectangles = []
x1 = 50
y1 = 50
x2 = 150
y2 = 100
for nr in range(10):
rectangle = self.canvas.create_rectangle(
x1 * nr, y1 * nr, x2 * nr, y2 * nr, fill='red')
self.rectangles.append(rectangle)
def change_color(self, color, index=0):
try:
rectangle = self.rectangles[index]
except IndexError:
return
self.canvas.itemconfig(rectangle, fill=color)
index += 1
self.app_win.after(1000, self.change_color, color, index)
def main():
app_win = tk.Tk()
app_win.attributes("-fullscreen", True)
app_win.bind("<Escape>", lambda e: app_win.quit())
app = Application(app_win)
app.change_color('green')
app_win.mainloop()
if __name__ == '__main__':
main()
Gruss wuf
Re: Tkinter-Rechteckobjekte mittels for-Schleife erstellen
Verfasst: Dienstag 10. Juli 2018, 07:03
von Sirius3
Das ganze ohne Index:
Code: Alles auswählen
import tkinter as tk
class Application(tk.Tk):
RECT_X1 = 50
RECT_Y1 = 50
RECT_X2 = 150
RECT_Y2 = 100
def __init__(self):
super().__init__()
self.width = self.winfo_screenwidth()
self.height = self.winfo_screenheight()
self.canvas = tk.Canvas(self, width=self.width, height=self.height,
highlightthickness=0, bg='black')
self.canvas.pack()
self.bind("<Escape>", lambda _: self.quit())
self.rectangles = [
self.canvas.create_rectangle(
self.RECT_X1 * nr, self.RECT_Y1 * nr, self.RECT_X2 * nr, self.RECT_Y2 * nr, fill='red')
for nr in range(10)
]
def change_next_rectangle(self, rectangles, color):
rectangle = next(rectangles, None)
if rectangle:
self.canvas.itemconfig(rectangle, fill=color)
self.after(1000, self.change_next_rectangle, rectangles, color)
def start_change_colors(self, color):
self.change_next_rectangle(iter(self.rectangles), color)
def main():
app = Application()
app.attributes("-fullscreen", True)
app.start_change_colors('green')
app.mainloop()
if __name__ == '__main__':
main()
Re: Tkinter-Rechteckobjekte mittels for-Schleife erstellen
Verfasst: Dienstag 10. Juli 2018, 22:13
von Atalanttore
Danke für die beiden Codebeispiele, aber welche von beiden Lösungen mit und ohne Index ist die bessere/elegantere?
Gruß
Atalanttore