Hallo Zusammen, bin Neu hier im Forum.
Mein Problem: Möchte dass die Farbfelder jeweils zufällig aufblinken und dies jeweils x (später einstellbar) mal. Leider blinken die Felder nach dem Drücken des Starbutton gleichzeitig auf. Ideal wäre ein Feld nach dem anderen. Ist hier threading angebracht bzw. falsch eingesetzt?
Danke im Voraus für eure Infos.
CODE:
from tkinter import *
import random
import time
import threading
root = Tk()
root.title("COLOR GAME")
def leucht_rot():
time.sleep(0.5)
b1.config(bg='red')
time.sleep(1)
b1.config(bg = '#8b0000')
def leucht_blau():
time.sleep(0.5)
b3.config(bg='blue')
time.sleep(1)
b3.config(bg = '#8470ff')
def leucht_gelb():
time.sleep(0.5)
b2.config(bg='yellow')
time.sleep(1)
b2.config(bg = '#ffd700')
def leucht_gruen():
time.sleep(0.5)
b4.config(bg='#00ff00')
time.sleep(1)
b4.config(bg = '#228b22')
# Zufällige helle Farben
def startb():
blist=(b1, b2, b3, b4)
def bzufall(blist):
return random.choice(blist)
for i in range(3):
if bzufall(blist) == b1:
threading.Thread(target=leucht_rot).start()
print("Button 1")
if bzufall(blist) == b2:
threading.Thread(target=leucht_gelb).start()
print("Button 2")
if bzufall(blist) == b3:
threading.Thread(target=leucht_blau).start()
print("Button 3")
if bzufall(blist) == b4:
threading.Thread(target=leucht_gruen).start()
print("Button 4")
# Funtion für Clicken der Buttons
def b_click(b):
pass
# Buttons erzeugen
b1 = Button(root, width=25, height=13, bg='#8b0000', command=lambda: b_click(b1))
b2 = Button(root, width=25, height=13, bg='#ffd700', command=lambda: b_click(b2))
b3 = Button(root, width=25, height=13, bg='#8470ff', command=lambda: b_click(b3))
b4 = Button(root, width=25, height=13 , bg='#228b22', command=lambda: b_click(b4))
start_button = Button(root, text='START', bg='black', fg='white', width=12, height=13, command = lambda: startb())
# Buttons gliedern
b1.grid(row=0, column=0)
b2.grid(row=1, column=0)
b3.grid(row=0, column=1)
b4.grid(row=1, column=1)
start_button.grid(row=0, column=2)
root.mainloop()
Blinkende Felder
Dieses Thema kommt hier immer wieder in der ein oder anderen Form. Zur Programmierung von zeitabhängigen Abläufen braucht man bei GUIs immer Timer. Im Fall von tkinter realisiert durch “after”. Zu dem them wurde hier schon viel diskutiert & Beispiele erbracht. Mal ein bisschen durch die Themen im tkinter Forum stöbern.
Benutze keine *-Importe, da das unkontrolliert hunderte Namen in den eigenen Namensraum schaufelt und man keine Übersicht hat, woher welcher Name kommt. Eingerückt wird immer mit 4 Leerzeichen pro Ebene, nicht mal 2 und mal 4.
Threads darf man mit GUI-Frameworks nicht benutzen, jedenfalls darf auf kein GUI-Element außerhalb des Hauptthreads zugreifen.
Alles was eine Funktion braucht, muß sie über ihre Argumente bekommen, also b1/b2/b3/b4 in den leucht-Funktionen.
Die vier Funktionen sind auch so ähnlich, dass man sie in eine zusammenfassen kann, aber da das sleep nicht verwendet werden darf, muß man es wieder in zwei aufspalten.
Wenn man anfängt Variablen durchzunummerieren, will man eigentlich eine passende Datenstruktur verwenden.
Benutze kein lambda, wo es einfach durch functools.partial ersetzbar ist.
In startb erzeugst Du 12 Zufallsknöpfe, die, wenn sie mit einem bestimmten Knopf übereinstimmen, wird die Farbe dieses Knopfes geändert, das passiert also 0 bis 12 mal. Ich glaube nicht, dass das gewollt ist.
Wenn Du die Buttons nacheinander leuchten lassen willst, mußt Du einen Button auswählen und diesen leuchten lassen, und mit after dann nach einer bestimmten Zeit den nächsten auswählen.
Threads darf man mit GUI-Frameworks nicht benutzen, jedenfalls darf auf kein GUI-Element außerhalb des Hauptthreads zugreifen.
Alles was eine Funktion braucht, muß sie über ihre Argumente bekommen, also b1/b2/b3/b4 in den leucht-Funktionen.
Die vier Funktionen sind auch so ähnlich, dass man sie in eine zusammenfassen kann, aber da das sleep nicht verwendet werden darf, muß man es wieder in zwei aufspalten.
Wenn man anfängt Variablen durchzunummerieren, will man eigentlich eine passende Datenstruktur verwenden.
Benutze kein lambda, wo es einfach durch functools.partial ersetzbar ist.
In startb erzeugst Du 12 Zufallsknöpfe, die, wenn sie mit einem bestimmten Knopf übereinstimmen, wird die Farbe dieses Knopfes geändert, das passiert also 0 bis 12 mal. Ich glaube nicht, dass das gewollt ist.
Wenn Du die Buttons nacheinander leuchten lassen willst, mußt Du einen Button auswählen und diesen leuchten lassen, und mit after dann nach einer bestimmten Zeit den nächsten auswählen.
Code: Alles auswählen
import tkinter as tk
import random
from functools import partial
BUTTON_COLORS = [
('red', '#4b0000'),
('blue', '#44708f'),
('yellow', '#ffd700'),
('#00ff00', '#228b22'),
]
def leuchte_on(button):
button['bg'] = button.highlight_color
button.after(1000, leuchte_off, button)
def leuchte_off(button):
button['bg'] = button.default_color
def start_colors(buttons):
for i in range(3):
for button in buttons:
if random.choice(buttons) == button:
button.after(500, leuchte_on, button)
# Funtion für Clicken der Buttons
def button_clicked(button):
pass
def main():
root = tk.Tk()
root.title("COLOR GAME")
# Buttons erzeugen
buttons = []
for index, (highlight_color, default_color) in enumerate(BUTTON_COLORS):
button = tk.Button(root, width=25, height=13, bg=default_color)
button['command'] = partial(button_clicked, button)
button.highlight_color = highlight_color
button.default_color = default_color
row, column = divmod(index, 2)
button.grid(row=row, column=column)
buttons.append(button)
start_button = tk.Button(root, text='START', bg='black', fg='white', width=12, height=13, command=partial(start_colors, buttons))
start_button.grid(row=0, column=2)
root.mainloop()
if __name__ == '__main__':
main()