Seite 1 von 1
GUI durch Berechnungen blockiert - Modul threading
Verfasst: Samstag 29. November 2008, 18:09
von pysq
Hallo,
ich arbeite mich gerade in das Modul threading ein, da ich es später für eine Client-Server-Architektur brauche.
Ich habe ein Beispielprogramm geschrieben, das noch nicht wie gewünscht funktioniert: Trotz threading wird die GUI blockiert, wenn im Hintergrund ein Thread ausgeführt wird. Dadurch wird es nicht möglich, einen neuen Thread zu starten.
Zum einfachen Beispielprogramm: Es handelt sich um einen Primzahlentest, der eine Zahl als Eingabe erwartet.
Code: Alles auswählen
import threading
from Tkinter import *
class MyThread(threading.Thread):
def __init__(self, number):
threading.Thread.__init__(self)
self.number = number
def run(self):
i=2
prim=True
while i*i < self.number:
if self.number%i==0:
prim=False
break
i+=1
print self.number, prim
def execute():
global all_threads
eingabe = e.get()
e.delete(0,999)
if eingabe == "ende":
global root
root.destroy()
for t in all_threads:
t.join()
return
thread = MyThread(int(eingabe))
all_threads.append(thread)
thread.start()
all_threads=[]
root=Tk()
e=Entry(root, width=10)
e.pack()
b=Button(root, text='Teste Zahl!', command = execute)
b.pack()
Kann mir bitte jemand helfen?
lg pysq
Verfasst: Samstag 29. November 2008, 18:35
von HWK
Wie wäre es mit
am Ende?
MfG
HWK
Verfasst: Montag 1. Dezember 2008, 20:42
von pysq
danke. habe nach schwerwiegenderen Fehlern gesucht

mfg pysq
Verfasst: Freitag 5. Dezember 2008, 22:45
von pysq
Hi!
Ich bin nun schon weitergekommen mit threading, stehe nun aber vor folgendem Problem:
Ich habe einen Clienten und einen Server.
Die run Methode der Klasse Client testet permanent auf empfangene Nachrichten. Der Server sendet genau 2 davon, die Nachrichten sind jeweils Methodennamen von
Client, die aber parameterlos sind.
Die erste Methode ist "CreateLabel". Sie erstellt ein Tkinter Label.
Die zweite Methode ist "DestroyLabel". Sie soll das Label wieder zerstören.
Doch das Label verschwindet leider nicht aus der GUI.
Weiß jemand, wo der Fehler liegt? danke wieder im Voraus!
client.py, vereinfacht
Code: Alles auswählen
import threading, socket
import Tkinter as tk
class Client(threading.Thread, tk.Tk):
def __init__(self, sock, ausschalter):
threading.Thread.__init__(self)
tk.Tk.__init__(self)
self.sock=sock
self.ausschalter=ausschalter
self.canvas=tk.Canvas(self)
self.canvas.pack()
def run(self):
while True:
rcvmsg = self.sock.recv(1024)
if rcvmsg:
# rcvmsg ist hier immer ein Methodenname von Test,
# der parameterlos ist
dargs = {}
if hasattr(self, rcvmsg):
getattr(self, rcvmsg)(**dargs)
def CreateLabel(self):
print 'func create'
self.l = tk.Label(self.canvas, text = 'Label', relief = 'groove')
self.canvas.create_window(50, 50, window = self.l)
def DestroyLabel(self):
print 'func destroy'
self.l.destroy()
self.canvas.update()
self.update()
ip = "127.0.0.1"
sock=socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.connect((ip, 50000))
ausschalter = threading.Event()
test = Client(sock, ausschalter)
test.start() # beginnt permanent auf Nachrichten zu testen
tk.mainloop()
server.py, vereinfacht
Code: Alles auswählen
import socket
import time
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind(("", 50000))
s.listen(1)
try:
while True:
komm, addr = s.accept()
print 'Client connected'
komm.send("CreateLabel")
time.sleep(1)
komm.send("DestroyLabel")
print 'ready'
finally:
s.close()
mfg pysq :]
Verfasst: Samstag 6. Dezember 2008, 01:00
von kaytec
Hallo pysq !
Falls du das Modul threading wegen der blockierten Gui verwendest, ist es auch moeglich diese Verhalten mit s.setblocking(0) zu verhindern. So kannst du auch die after Methode verwenden.
gruss frank
Verfasst: Samstag 6. Dezember 2008, 11:02
von pysq
Hallo!
Ich verwende threading, um im Hintergrund einer GUI auf Nachrichten von einem Server zu warten. Der Nutzer kann also noch verschiedene andere Operationen in der GUI durchführen.
Konkret handelt es sich um ein Kartenspiel (ähnlich Skat), dass ich in Form eines Netzwerkspiels implementieren will. Das Spiel selbst soll auf dem Server laufen.
Der Client erhält vom Server jedes mal, wenn eine Karte gelegt wird ein Nachricht, das der Kartenstapel geupdatet werden soll (vgl. "CreateLabel" - erstellt eine Karte).
Wenn ein Kartenstich vollständig ist, erhält der Client den Befehl, den Kartenstapel wieder zu leeren vgl. "DestroyLabel"). Letzteres funktioniert nicht richtig.
s.setblocking(0) selbst ändert an dem Problem noch nichts. Was ist die after Methode? Ich habe sie in den Module Docs/ Python Manuals nicht gefunden.
mfg pysq
Verfasst: Samstag 6. Dezember 2008, 11:08
von numerix
pysq hat geschrieben:Was ist die after Methode? Ich habe sie in den Module Docs/ Python Manuals nicht gefunden.
after
Verfasst: Samstag 6. Dezember 2008, 12:42
von pysq
danke! es funktioniert soweit bei parameterlosen Funktionen! : )
Eines noch:
Ich will nun mit der after Methode eine Funktion mit Parametern aufrufen. Die Parameter liegen in einen Dictionary vor.
Wie kann ich alle Argumente des Dictionaries an die mit after per callback aufgerufene Funktion übergeben?
mfg pysq
Verfasst: Samstag 6. Dezember 2008, 13:17
von numerix
pysq hat geschrieben:Ich will nun mit der after Methode eine Funktion mit Parametern aufrufen. Die Parameter liegen in einen Dictionary vor.
Wie kann ich alle Argumente des Dictionaries an die mit after per callback aufgerufene Funktion übergeben?
Variante 1:
Das Dictionary als Attribut an eine Instanz binden, die auch im Event-Handler verfügbar ist (so eine Art "global" Ersatz)
Variante 2:
Einen lambda-Ausdruck bauen. Im Zusammenhang mit Callbacks:
http://www.ferg.org/thinking_in_tkinter ... grams.html
Speziell die Programme tt078.py und tt079.py mit den entsprechenden Erläuterungen.
Verfasst: Samstag 6. Dezember 2008, 20:02
von pysq
jetzt funktioniert alles! nochmal thx :]