PyQt und thread

Python und das Qt-Toolkit, erstellen von GUIs mittels des Qt-Designers.
Antworten
Hillkorn
User
Beiträge: 12
Registriert: Samstag 19. Januar 2008, 19:31
Kontaktdaten:

Sonntag 27. Januar 2008, 20:11

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
lunar

Dienstag 29. Januar 2008, 20:13

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.
Hillkorn
User
Beiträge: 12
Registriert: Samstag 19. Januar 2008, 19:31
Kontaktdaten:

Donnerstag 31. Januar 2008, 18:09

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
burli
User
Beiträge: 1116
Registriert: Dienstag 9. März 2004, 18:22

Freitag 29. Februar 2008, 08:21

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 :)
BlackJack

Freitag 29. Februar 2008, 08:32

@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.
lunar

Freitag 29. Februar 2008, 09:02

BlackJack hat geschrieben:@lunar: Vergleiche auf Boolean sollte man *nicht* mit ``is`` durchführen!
Stimmt, mein Fehler.
burli
User
Beiträge: 1116
Registriert: Dienstag 9. März 2004, 18:22

Freitag 29. Februar 2008, 09:07

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?
Leonidas
Administrator
Beiträge: 16024
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

Freitag 29. Februar 2008, 09:58

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.
My god, it's full of CARs! | Leonidasvoice vs Modvoice
Antworten