Seite 1 von 1

PyQt und thread

Verfasst: Sonntag 27. Januar 2008, 20:11
von Hillkorn
Hi ich will einen Thread starten der in einem PyQt Mainwindow empfangene nachrichten ausgibt und das am besten über einen thread

klappt an sich alles bis auf das ich das ganze ins fenster bekomm.
Sobald der befehl dazu kommt stürzt das programm immer ab :(
Ohne thread geht es!

Code: Alles auswählen

import socket
import sys
from PyQt4 import QtCore, QtGui
from Ui_client import Ui_MainWindow as Dlg
import thread
import time

class CDlg(QtGui.QMainWindow, Dlg):
    def __init__(self, s):
        QtGui.QMainWindow.__init__(self)
        self.setupUi(self)
        self.show()
        
        self.s = s
        
        self.connect(self.Connect, QtCore.SIGNAL("clicked()"),  self.onConnect)
        self.connect(self.Sender, QtCore.SIGNAL("clicked()"),  self.onSend)
        
        
    def onSend(self):
        self.s.send("Hillkorn: %s\n" % self.Inputbox.toPlainText())
        self.Inputbox.clear()
        
    def onConnect(self):
        self.s.connect(("127.0.0.1", 51000))
        global ct
        ct = True
        
    def onEmpf(self, nachricht):
        #  nachricht = self.s.recv(1024)
        #  nachricht = self.Outputbox.toPlainText() + nachricht
        self.Outputbox.setPlainText(nachricht)
  


def empfangen():
    global ct
    global nachricht
    global s
    global window
    print "out if"
    while True:
        if ct == True:
            print "in if"
            nachricht += s.recv(1024)
            window.onEmpf(nachricht)
        time.sleep(2)
        

#ip = raw_input("IP-Adresse: ")
#name = raw_input("Ihr name? ")
#s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
#s.connect((ip, 51000))

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
ct = False
nachricht = ""
app = QtGui.QApplication(sys.argv)
window = CDlg(s)
thread.start_new_thread(empfangen, ())
sys.exit(app.exec_())
SRY ich weiß geht besser zu schreiben aber hab den code so oft verändert ohne ergebnisse das es jetz halt einfach nur funktionieren soll

Schonmal danke und freu mich über jeden rat

Verfasst: Dienstag 29. Januar 2008, 20:13
von lunar
Auf GUI-Elemente kann man nur aus dem erzeugenden Thread zugreifen. Du erzeugst einen zweiten Thread, und rufst die Funktion CDlg.onEmpf aus diesem Thread heraus auf. Das funktioniert in keinem einzigen mir bekannten GUI-Toolkit.

Du musst den gesamten Code, der direkt auf Widgets zugreift, in einem einzigen Thread ablaufen lassen. Das kannst du auf komplizierte Weise tun, in dem du Python's threading Modul mit Events koppelst, und die Daten über eine globale Variable austauscht. Oder du erledigst das auf einfache Weise, in dem du Qt's QThread-Klasse verwendest, und bei empfangenen Daten ein Signal aussendest, welches von einem Slot in CDlg empfangen wird. Dieser Slot kümmert sich dann um den GUI-Zugriff. Der Vorteil ist, dass Qt4 die Synchronisierung automatisch übernimmt, so dass du dich gar nicht erst um Threading-Issues kümmern musst. Dazu gibt es in der Qt4-Dokumentation auch ein gutes Beispiel (das klassische Mandelbrot-Programm ;) ).

Noch ein paar Anmerkungen zum Code:
  • Englische Bezeichner verwenden. Du weißt nie, wer den Code so lesen wird.
  • global ist evil.
  • Vergleiche mit Boolean-Singletons sollten laut PEP8 nicht mit ==, sondern mit dem isKeyword durchgeführt werden. Der Vergleich ist aber auch komplett überflüssig, da bool'sche Objekte in Abfragen direkt ausgewertet werden.

Verfasst: Donnerstag 31. Januar 2008, 18:09
von Hillkorn
yeah ne antwort :D

Jo das mit den globals war auch echt nur proba halber^^

Mit den bezeichnern werd ich mir merken... und hab ich auch zum teil schon in c++ progs mit angefangen

Und beim dritten weiß ich nicht was du meinst... müsst ich nochmal suchen

Aber werds mal mit QThread probieren

Verfasst: Freitag 29. Februar 2008, 08:21
von burli
Soweit ich das weiß sollte man in Zusammenhang mit Qt auch die QThreads verwenden. Vom Hauptthread kann man glaub ich über Methoden auf den Secondary Thread zugreifen, umgekehrt kann man Signal/Slot verwenden.

So hab ich es zumindest kürzlich gelesen :)

Verfasst: Freitag 29. Februar 2008, 08:32
von BlackJack
@lunar: Vergleiche auf Boolean sollte man *nicht* mit ``is`` durchführen! Das kann sehr leicht daneben gehen, weil 1. viele andere Objekte auch als "wahr" oder "falsch" herhalten können und 2. es in der Vergangenheit üblich war sich `True` und `False` selbst als Aliase für 1 und 0 zu definieren. Die Namen gab's nämlich nicht von Anfang an.

Verfasst: Freitag 29. Februar 2008, 09:02
von lunar
BlackJack hat geschrieben:@lunar: Vergleiche auf Boolean sollte man *nicht* mit ``is`` durchführen!
Stimmt, mein Fehler.

Verfasst: Freitag 29. Februar 2008, 09:07
von burli
BlackJack hat geschrieben:Vergleiche auf Boolean sollte man *nicht* mit ``is`` durchführen!
Kann man es denn, rein technisch gesehen? Sprich: der Interpreter meckert nicht?

Verfasst: Freitag 29. Februar 2008, 09:58
von Leonidas
burli hat geschrieben:
BlackJack hat geschrieben:Vergleiche auf Boolean sollte man *nicht* mit ``is`` durchführen!
Kann man es denn, rein technisch gesehen? Sprich: der Interpreter meckert nicht?
Natürlich. ``is``-Vergleiche funktionieren immer zwischen zwei Objekten. Im Falle von ``True`` und ``False`` funktioniert das ja auch, da ``True`` und ``False`` ebenso wie ``None`` Singletons sind, d.h. man bekommt immer die gleiche Instanz zurück, somit funktioniert der Vergleich durchaus. Nur ist das eben nicht die beste Lösung, wie BlackJack schon erläutert hat.