Foros del Web » Programando para Internet » Python »

Problema con Threads y QT

Estas en el tema de Problema con Threads y QT en el foro de Python en Foros del Web. Hola a todos, estoy tratando de crear un chat en Python usando como Interfaz grafica QT, tengo el siguientes codigo: server.py @import url("http://static.forosdelweb.com/clientscript/vbulletin_css/geshi.css"); Código Python: ...
  #1 (permalink)  
Antiguo 25/08/2012, 20:20
 
Fecha de Ingreso: diciembre-2011
Mensajes: 26
Antigüedad: 13 años
Puntos: 5
Exclamación Problema con Threads y QT

Hola a todos, estoy tratando de crear un chat en Python usando como Interfaz grafica QT, tengo el siguientes codigo:

server.py
Código Python:
Ver original
  1. import asyncore, socket
  2.  
  3. clients = {}
  4.  
  5. class MainSocketServer(asyncore.dispatcher):
  6.     def __init__(self, puerto):
  7.         asyncore.dispatcher.__init__(self)
  8.         self.create_socket(socket.AF_INET, socket.SOCK_STREAM)
  9.         self.bind(('', puerto))
  10.         self.listen(10)
  11.  
  12.     def handle_accept(self):
  13.         newSocket, address = self.accept()
  14.         clients[address] = newSocket
  15.         print "Conectado desde", address
  16.         SecondSocketServer(newSocket)
  17.  
  18. class SecondSocketServer(asyncore.dispatcher_with_send):
  19.     def handle_read(self):
  20.         mensaje = self.recv(1000)
  21.         if mensaje:
  22.             clientes = clients.values()
  23.             for cliente in clientes:
  24.                 cliente.send(mensaje+'\n')
  25.         else:
  26.             self.close()
  27.  
  28.     def handle_close(self):
  29.         print "Desconectado desde", self.getpeername()
  30.         del clients[self.getpeername()]
  31.  
  32. MainSocketServer(9090)
  33. asyncore.loop()



client.py
Código Python:
Ver original
  1. from PySide import QtGui, QtCore
  2. import socket, thread, sys
  3.  
  4. socket_cliente = socket.socket()
  5. socket_cliente.connect(('', 9090))
  6.  
  7. class Window(QtGui.QMainWindow):
  8.     def __init__(self):
  9.         super(Window, self).__init__()
  10.         self.socket()
  11.  
  12.         self.browser = QtGui.QTextBrowser()
  13.         self.browser.backwardAvailable
  14.  
  15.         self.textEdit = QtGui.QTextEdit()
  16.         self.textEdit.setMaximumSize(QtCore.QSize(400, 60))
  17.  
  18.         self.connect(self.browser, QtCore.SIGNAL("returnPressed()"), self.enviar_mensaje)
  19.  
  20.         enviarB = QtGui.QPushButton("Enviar")
  21.         enviarB.setMaximumSize(QtCore.QSize(400, 60))
  22.         enviarB.clicked.connect(self.enviar_mensaje)
  23.  
  24.         layoutINlayout = QtGui.QHBoxLayout()
  25.         layoutINlayout.addWidget(self.textEdit)
  26.         layoutINlayout.addWidget(enviarB)
  27.  
  28.         widget = QtGui.QWidget()
  29.         self.setCentralWidget(widget)
  30.  
  31.         self.layout = QtGui.QVBoxLayout()
  32.         self.layout.addWidget(self.browser)
  33.  
  34.         mainWindow = QtGui.QVBoxLayout()
  35.         mainWindow.addLayout(self.layout)
  36.         mainWindow.addLayout(layoutINlayout)
  37.  
  38.         widget.setLayout(mainWindow)
  39.         self.setWindowFlags(QtCore.Qt.WindowTitleHint)
  40.  
  41.     def enviar_mensaje(self):
  42.         mensaje = self.textEdit.toPlainText()
  43.         socket_cliente.send(mensaje)
  44.  
  45.     def add_mensaje(self, mensaje):
  46.         self.browser.setText(mensaje)
  47.  
  48.     def socket(self):
  49.         def loop():
  50.             while True:
  51.                 mensaje = socket_cliente.recv(1000)
  52.                 if mensaje:
  53.                     self.add_mensaje(mensaje)
  54.  
  55.         thread.start_new_thread(loop, ())
  56.  
  57. app = QtGui.QApplication(sys.argv)
  58. w = Window()
  59. w.show()
  60. app.exec_()

El servidor en realidad no da ningun problema, pero el cliente me da el siguiente error:

Código:
QObject: Cannot create children for a parent that is in a different thread.
(Parent is QTextDocument(0x95e29f0), parent's thread is QThread(0x9140ea0), current thread is QThread(0xafe009a0)
Violación de segmento (`core' generado)
Estuve revisando y este error da en la linea 53 de client.py al tratar de acceder a la funcion add_mensaje de la clase Window, no se si esque el thread no tiene permiso para acceder a las funciones de la clase o algo asi porque si cambio la linea 53 por "print mensaje", me imprime bien el mensaje que llega.

Espero me puedan ayudar con esto

Última edición por samuelb1311; 25/08/2012 a las 20:54
  #2 (permalink)  
Antiguo 26/08/2012, 09:16
Avatar de jhg
jhg
 
Fecha de Ingreso: marzo-2012
Mensajes: 96
Antigüedad: 12 años, 8 meses
Puntos: 1
Respuesta: Problema con Threads y QT

Por lo que veo del error y de tu código (aviso que no he usado la biblioteca QT) es que lanzas en un hilo una función que es un método de una clase e intentas desde el hilo acceder a objetos de QT del otro hilo, y por lo visto QT no te permite hacer eso así de directo y arriesgado. Seguramente QT tenga su propia forma de manejar hilos (mirala, quizas te saltes algunas restricciones de GIL) y el acceso a los objetos QT. Mira tambien si es segura con hilos.
__________________
JHG
  #3 (permalink)  
Antiguo 26/08/2012, 12:48
 
Fecha de Ingreso: diciembre-2011
Mensajes: 26
Antigüedad: 13 años
Puntos: 5
De acuerdo Respuesta: Problema con Threads y QT

Bueno ya pude resolverlo, la manera de hacerlo en QT es usando el sistema de SIGNAL y SLOTS, emitiendo una Señal en el thread cuando llega el mensaje, para que el parent thread lo gestione, aqui va el codigo del client.py por si a alguien le sirve:

Código Python:
Ver original
  1. from PySide import QtGui, QtCore
  2. import socket, thread, sys
  3.  
  4. socket_cliente = socket.socket()
  5. socket_cliente.connect(('', 9090))
  6.  
  7. class Window(QtGui.QMainWindow):
  8.     def __init__(self):
  9.         super(Window, self).__init__()
  10.         self.socket()
  11.  
  12.         self.browser = QtGui.QTextBrowser()
  13.         self.browser.backwardAvailable
  14.  
  15.         self.textEdit = QtGui.QTextEdit()
  16.         self.textEdit.setMaximumSize(QtCore.QSize(400, 60))
  17.  
  18.         self.connect(self.browser, QtCore.SIGNAL("returnPressed()"), self.enviar_mensaje)
  19.         self.connect(self, QtCore.SIGNAL("agregarMensaje(QString)"), self.imprime)
  20.  
  21.         enviarB = QtGui.QPushButton("Enviar")
  22.         enviarB.setMaximumSize(QtCore.QSize(400, 60))
  23.         enviarB.clicked.connect(self.enviar_mensaje)
  24.  
  25.         layoutINlayout = QtGui.QHBoxLayout()
  26.         layoutINlayout.addWidget(self.textEdit)
  27.         layoutINlayout.addWidget(enviarB)
  28.  
  29.         widget = QtGui.QWidget()
  30.         self.setCentralWidget(widget)
  31.  
  32.         self.layout = QtGui.QVBoxLayout()
  33.         self.layout.addWidget(self.browser)
  34.  
  35.         mainWindow = QtGui.QVBoxLayout()
  36.         mainWindow.addLayout(self.layout)
  37.         mainWindow.addLayout(layoutINlayout)
  38.  
  39.         widget.setLayout(mainWindow)
  40.         self.setWindowFlags(QtCore.Qt.WindowTitleHint)
  41.  
  42.     def imprime(self, mensaje):
  43.         self.add_mensaje(mensaje)
  44.  
  45.     def enviar_mensaje(self):
  46.         mensaje = self.textEdit.toPlainText()
  47.         socket_cliente.send(mensaje)
  48.  
  49.     def add_mensaje(self, mensaje):
  50.         self.browser.setText(mensaje)
  51.  
  52.     def socket(self):
  53.         def loop():
  54.             while True:
  55.                 print "Esperando mensajes"
  56.                 mensaje = socket_cliente.recv(1000)
  57.                 if mensaje:
  58.                     self.emit(QtCore.SIGNAL("agregarMensaje(QString)"), mensaje)
  59.  
  60.         thread.start_new_thread(loop, ())
  61.  
  62. app = QtGui.QApplication(sys.argv)
  63. w = Window()
  64. w.show()
  65. app.exec_()

Etiquetas: chat, pyqt, pyside
Atención: Estás leyendo un tema que no tiene actividad desde hace más de 6 MESES, te recomendamos abrir un Nuevo tema en lugar de responder al actual.
Respuesta




La zona horaria es GMT -6. Ahora son las 01:33.