GUI öffnen, Programm weiterlaufen lassen

Fragen zu Tkinter.
Antworten
jompel
User
Beiträge: 3
Registriert: Dienstag 23. Juni 2015, 20:30

Hallo,
ich möchte gerne mit time.sleep(5) dafür sorgen, dass der Reihe nach in meinem Tkinter-Fenster ausgegeben wird, dass Lampe x leuchtet, dann Lampe y, dann Lampe z, usw.

Mein Problem ist, dass das als Konsolenausgabe soweit ohne Probleme funktioniert hat. Sobald ich das Tkinter-Fenster mit mainloop() jedoch starte, geht der Ablauf nicht mehr voran :K

Wie kann ich den Code anpassen, damit sich der Text ändert, nachdem die GUI erzeugt wurde?

Code: Alles auswählen

import time
from Tkinter import *

# Erzeugung des Fensters
tkFenster = Tk()
tkFenster.title('Lampen GUI')

# Label fuer die Lampen
w = Canvas(tkFenster, width=200, height=100)
w.pack()
 
# Label-Erzeugung
lampenstatus = Label(text="Test")
lampenstatus.pack()
 
# Uebernahme der Lampensignale
def output(lampe, status):
    if (status == 0):
        print ("Lampe " + str(lampe) + " ist ausgeschaltet.")
        lampenstatus.configure(text=("Lampe " + str(lampe) + " ist ausgeschaltet."))
    else:
        print ("Lampe " + str(lampe) + " ist eingeschaltet.");
        lampenstatus.configure(text=("Lampe " + str(lampe) + " ist eingeschaltet."))
 
# Lampe 21 wird ausgeschaltet
output(21,0)
time.sleep(5)
 
# Lampe 20 wird ausgeschaltet
output(20,0)
time.sleep(5)

# Aktivierung des Fensters
tkFenster.mainloop()
 
# Lampe 15 wird eingeschaltet
output(15,1)
jompel
User
Beiträge: 3
Registriert: Dienstag 23. Juni 2015, 20:30

Hat sich erledigt, mainloop() musste einfach in einen eigenen Thread.
BlackJack

@jompel: Das ist nicht die einfachste Lösung und wenn man nicht weiss was man tut auch ”gefährlich” denn Tkinter ist wie die meisten GUI-Rahmenwerke nicht uneingeschränkt thread-sicher. Man darf die GUI nur aus dem Thread heraus manipulieren in dem die GUI-Hauptschleife läuft und das sollte der Hauptthread sein. Alles andere führt zu undefiniertem Verhalten.

Bei GUI-Programmen muss man umdenken und von einem rein linearen Programmablauf auf einen ereignisbasierten umsteigen. Die `mainloop()` ist, nun ja die Hauptschleife. Die muss hauptsächlich laufen damit die GUI funktioniert, wenn notwendig aktualisiert, und auf den Benutzer reagieren kann.

Das in einem gewissen zeitlichen Abstand etwas passieren soll kann man mit der `after()`-Methode auf Widgets erreichen. Also statt `time.sleep()` jeden Schritt als Rückruffunktion bei Tk registrieren die nach der angegeben Zeit dann aufgerufen wird.

Sonstige Anmerkungen: Sternchen-Importe sollte man vermeiden. Da holt man sich alle Namen aus einem anderen Modul in das Importierende. Es wird schnell unübersichtlich welcher Name eigentlich woher kommt und es besteht die Gefahr von Namenskollisionen.

Die Namen halten sich nicht alle an den Style Guide for Python Code und `w` ist als Name ein wenig zu nichtssagend. Zumal der Kommentar vor der Definition nicht stimmt: da wird gar kein Label erzeugt sondern ein Canvas. Was man aber nicht kommentieren braucht denn das sieht man ja deutlich im Code.

Auf Modulebene gehört nur Code der Konstanten, Funktionen, und Klassen definiert. Das Hauptprogramm steckt üblicherweise in einer `main()`-Funktion. Das führt dann zwangsläufig zu objektorientierter Programmierung (OOP) — da kommt man bei GUI-Programmierung in Python kaum drum herum.

Widgets sollte man immer ein Elternwidget übergeben. Beim `lampenstatus` tust Du das nicht.

Die Klammern um die ``if``-Bedingung sind unnötig, genau so Semikolons am Ende einer Anweisung. Das gilt auch für die Klammern bei den ``print``-Anweisungen.

Um Werte in Zeichenketten zu formatieren verwendet man in Python Zeichenkettenformatierung mit der `format()`-Methode auf Zeichenketten statt das unübersichtlich mit `str()` und ``+`` zusammen zu stückeln. In der `output()`-Funktion ist auch ziemlich viel Code wiederholt. Die beiden Zweige unterscheiden sich ja nur durch die Wortteile 'ein' und 'aus'.
Antworten