TKinter Threads

Fragen zu Tkinter.
Antworten
flou
User
Beiträge: 4
Registriert: Mittwoch 2. Juni 2010, 09:50

Morgen,

bin seit einigen Wochen dabei, mir Python anzulesen/ zu tippen.
Momentan versuche ich mich an einer Chat Applikation...
Nachdem die Basics klar waren, hab ich mich an Threads versucht.
Nach einigen Verzweiflungen hab ichs grade so hinbekommen, und hab mich jetzt mit TKinter
beschäftigt. Als ich dann aber versucht habe, GUI und Threads zu verbinden, klappen die Threads wieder nicht, und ich habe auch soweit keinen Plan mehr..

Code: Alles auswählen

from Tkinter import *
import socket
import threading
from threading import Thread
import time

global s
global root
class Application(Frame, threading.Thread):
    def __init__(self, master=None):
        self.started=0
        root = Tk()
        Frame.__init__(self, master)
        self.grid()
        self.createWidgets()
        self.textfenster()
    def send(self):
        self.nachricht = self.entry.get()
        self.komm.send(self.nachricht)
    def createWidgets(self):
        enter=Frame(self)
        enter.pack(side=BOTTOM)
        self.entry = Entry(enter)
        self.entry.pack(side=LEFT,padx=10,pady=12)
        self.sendbutton = Button(enter, text='Senden', command = self.send)
        self.connbutton = Button(enter, text='Verbinden', command = self.star)
        self.sendbutton.pack(side=RIGHT)
        self.connbutton.pack(side=RIGHT)
    def textfenster(self):
        textfr = Frame(self)
        self.text=Text(textfr, height=10,width=50,background='white', borderwidth=5)
        textfr.pack(side=RIGHT)
        self.text.pack(side=TOP)
    def star(self):
        self.s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        self.s.setsockopt( socket.SOL_SOCKET, socket.SO_REUSEADDR, 1 )
        self.s.bind(("", 20000)) 
        self.s.listen(1)
        self.komm, self.addr = self.s.accept()
        self.recc=self.rec(self)
        self.recc.start()    
[i]# Hier sollte der Thread initialisiert werden, allerdings führt mir das Script nur noch den Thread aus..[/i]
        print'Done..'
    def rec(self, Thread): #Hier sollte der Thread beginnen
        while True:
            time.sleep(0.5)
            self.s.settimeout(0.1)
            self.data = self.komm.recv(1024)
            if self.data:
                self.text.config(state=NORMAL)
                self.text.insert(END, self.data)
                self.text.config(state=DISABLED)

        


app = Application()
app.mainloop()

Hoffe der Code ist soweit übersichtlich, aber Kommentare hab ich bisher nicht gebraucht..
Danke im Vorraus
Zuletzt geändert von Leonidas am Mittwoch 2. Juni 2010, 13:36, insgesamt 1-mal geändert.
Grund: Ins Tkinter-Forum verschoben
EyDu
User
Beiträge: 4881
Registriert: Donnerstag 20. Juli 2006, 23:06
Wohnort: Berlin

Hallo und willkommen im Forum!

Der Code sieht wirklich sehr unsauber aus und es hat den Anschein, als wenn du GUIs noch nicht wirklich verstanden hast. Mit GUIs und Threading anzufangen halte ich nicht für besonders klug. Beides sind sehr komplexe Themen mit sehr vielen Tücken.

Zunächst ist die Mehrfachvererbung hier vollkommen falsch. Was du haben möchtest ist eine Klasse für die GUI, eine Thread zum Lesen von einkommenden Nachrichten und ein Thread zum Schreiben von ausgehenden Nachrichten. Du musst aber beachten, dass du auf keinen Fall aus den Threads auf die GUI zugreifst! Dazu gibt es bei Tkinter eine after-Methode, mit der du periodisch die Status der Threads abfragen kannst. Am besten in Verbindung mit Queues.

Noch ein paar Anmerkungen zu deinem Code:
- benutze keine *-importe
- warum "import threading" und "from threading import Thread"
- global ist böse und du möchtest es auf keinen Fall benutzen
- entscheide dich für eine Sprache: entweder deutsch oder englisch, aber nicht beides gemischt

Sebastian
Das Leben ist wie ein Tennisball.
flou
User
Beiträge: 4
Registriert: Mittwoch 2. Juni 2010, 09:50

Ja, der Code ist noch nicht fertig, erst mal sollte das Script soweit laufen...
Dann hätte ich mich an den Feinschliff gemacht.
Zum Einsteigen, naja das is so ne Sache... Hatte aber gehofft, ich käme um die Queues herum.
Gut, dann m ach ich mich mal an die Arbeit.
Danke

P.S.: Das import threading und from threading import * kommt von verschiedenen
Experimenten mit Threads anhand von Beispielen. Wäre aber sicher noch irgendwann geflogen ;)
EyDu
User
Beiträge: 4881
Registriert: Donnerstag 20. Juli 2006, 23:06
Wohnort: Berlin

Hallo.
flou hat geschrieben:Ja, der Code ist noch nicht fertig, erst mal sollte das Script soweit laufen...
Meine Anmerkungen waren kein Feinschliff. Der jetzige Code hat gravierende Mängel im Design und der Umsetzung. Die lassen sich am Ende nicht einfach schnell ausbügeln. Du solltest dir angewöhnen gleich, zumindest halbwegs, vernünftigen Code zu schreiben. Das übt uns spart eine Menge Zeit. Auch wenn du letzteres sicher nicht sofort einsehen wirst ;-)

Bis dann,
Sebastian
Das Leben ist wie ein Tennisball.
flou
User
Beiträge: 4
Registriert: Mittwoch 2. Juni 2010, 09:50

Schon klar..
Ich hatte auch nur nen kurzen Ausschnitt genommen, weil das Programm alle halbe Stunde ganz anders aussieht... Zugegebenermaßen bin ich noch en ziemlicher noob was Python angeht.
Aber mal ne andere Frage:
Hab gelesen, die after Methode würde den Ablauf der mainloop unterbrechen, was nicht unbedingt das ist, was ich möchte. Wie könnte ich denn trotz allem von einem Thread aus (der nicht in der GUI Klasse enthalten ist ;)) auf die GUI zugreifen?

Edit: Weil ichs grade lese, n Thread zum schreiben von senden von Nachrichten brauche ich nicht, denn ein Button übernimmt ja die Funktion.. Ich brauche prinzipiell nur nen Thread um nach eingegangenen Nachrichten zu gucken.
BlackJack

@flou: Die `after()`-Methode oder besser gesagt die dort angegebene Rückruffunktion blockiert halt solange der Rückruf abgearbeitet wird. Aber der läuft ja nicht lange, da soll ja nur geprüft werden ob eine Änderung an der GUI nötig ist, und falls ja, wird diese Änderung durchgeführt.

Threads sind nicht in Klassen enthalten. Die sind unabhängig von solchen Einteilungen des Codes. Und es gibt keine Alternative dazu nur von dem Thread aus auf die GUI zuzugreifen, in dem auch die `mainloop()` von Tk läuft.
Antworten