Найти - Пользователи
Полная версия: PyQt Проблема с приемом сигнала.
Начало » GUI » PyQt Проблема с приемом сигнала.
1
SHS
Привет.
Есть форма в которую импортирую собственный класс (QObject).
Форма запускает поток QThread,
Поток QThread обращается к импортированному классу за методом.
Метод циклично сигнализирует.
Форма должна принимать эти сигналы и вписывать их значение в ListWidget. Но вот почему то не принимает…
Пробовал QThread'ом принимать сигнал, а потом передавать его на форму - не получилось тоже.
Как правильно принять сигнал?

#mainForm.py
# Форма содержит кнопку "GO" и ListWidget

from PyQt4.QtCore import *
from PyQt4.QtGui import *
from Ui_form import *
from myclasses import MYCLASS


class DoWork(QThread):


def __init__(self):
QThread.__init__(self)
self.mycl = MYCLASS()

def run(self):
#Вызываем функцию из импортированного класса QObject
self.mycl.printMsg()

def __del__(self):
self.exiting = True
self.wait()


class MainForm(QMainWindow):


def __init__(self, parent=None):
QWidget.__init__(self, parent)
self.ui = Ui_MainForm()
self.ui.setupUi(self)

self.ui.getBasesButton.clicked.connect(goButton_OnClick)

#Нажатие на кнопку GO
def goButton_OnClick(self):
self.mycl = MYCLASS()
self.t = DoWork()
self.mycl.strSignal.connect(self.addToList, type=Qt.QueuedConnection)
self.t.start()

#Слот добавляет полученный текст в ListWidget
@pyqtSlot(str)
def addToList(self, msg)
self.ui.listWidget.addItem(msg)


if __name__ == "__main__":
import sys
app = QApplication(sys.argv)
myapp = MainForm()
myapp.show()
sys.exit(app.exec_())


#myclasses.py

from PyQt4.QtCore import *
from PyQt4.QtGui import *


class MYCLASS(QObject):


strSignal = pyqtSignal(str)

def __init__(self):
QObject.__init__(self)

def printMsg(self):
while True:
i += 1
self.strSignal.emit(str(i))
time.sleep(0.1)
if i == 10:
break
dimabest
знакомая проблема :)
читай http://python.su/forum/viewtopic.php?id=6829
dimabest
этот мусор нужно убрать :)
    def __del__(self):
self.exiting = True
self.wait()
SHS
Спасибо за помощь, но можно небольшой пример используя мой код?
Просто я то-то не въеду никак, хотя перечитал пост много раз))
Кстати хочу этот класс сделать независимым, т. е. чтоб где угодно и кто угодно мог его импортировать и использовать. Модуль в общем.
Может использовать не QObject?
dimabest
Суть в том, что сигнал должен посылать объект потока.

Oкей, держи готовый код.

taskpool.py
# coding: utf8

import sys
import Queue

from PyQt4.QtCore import QThread, SIGNAL, QObject


class Task(object):
error = None


class Thread(QThread):
def __init__(self, queue):
QThread.__init__(self)
self.queue = queue

def run(self):
while True:
task, callback = self.queue.get()
try:
task()
except:
task.error = sys.exc_info()
self.emit(SIGNAL('taskDone(PyQt_PyObject, PyQt_PyObject)'), task, callback)


class TaskPool(object):
def __init__(self, size):
self._pool = []
self._queue = Queue.Queue()

for _ in range(size):
t = Thread(self._queue)
self._pool.append(t)
QObject.connect(t, SIGNAL('taskDone(PyQt_PyObject, PyQt_PyObject)'), self._done)
t.start()

def put(self, task, callback=None):
self._queue.put((task, callback))

def _done(self, task, callback):
if callback:
callback(task)
test.py
# coding: utf8

import sys

import urllib2
import traceback

from PyQt4.QtGui import *
from PyQt4.QtCore import *

from taskpool import TaskPool, Task



class MyTask(Task):
# через конструктор передаем любые параметры
def __init__(self, url):
self.url = url
# метод, который будет вызван в потоке
def __call__(self):
source = urllib2.urlopen(self.url).read()
self.size = round(len(source) / 1024)


URLS = ['http://www.apple.com', 'http://www.yandex.ua', 'http://www.google.com', 'http://www.yahoo.com', 'http://www.microsoft.com', 'http://unknown-site.com']

class Main(QWidget):
def __init__(self):
QWidget.__init__(self)
self.layout = QVBoxLayout()
self.button = QPushButton('Start')
QObject.connect(self.button, SIGNAL('clicked()'), self.start)
self.layout.addWidget(self.button)
self.setLayout(self.layout)
# создаем пул потоков, параметр - количество потоков
self.pool = TaskPool(6)

# метод будет вызван для каждой задачи. Вызван в главном потоке, поэтому можно обновлять GUI и т.д.
def callback(self, task):
# если задача в потоке "вылетит" с ошибкой, необработанное исключение
# будет перехвачено и записано в свойство error - type, value, traceback
if task.error:
print 'ERROR for URL %s' % task.url
traceback.print_exception(*task.error)
else:
print 'URL: %s SIZE: %d KB' % (task.url, task.size)

def start(self):
for url in URLS:
# создаем задачу
task = MyTask(url)
# кладем в пул задачу и необязательную функцию обратного вызова
self.pool.put(task, self.callback)

app = QApplication(sys.argv)
w = Main()
w.show()
sys.exit(app.exec_())
Для каждой задачи, которая должна выполнятся в потоке создаешь класс, наследуя его от Task. В примере создается MyTask. Параметром он получает URL страницы, которую в потоке должен скачать и подсчитать размер.

В список URL-ов добавил http://unknown-site.com чтобы одна из задач, выполняемая в потоке вылетела с ошибкой.
Код предельно простой, думаю разберешся.
SHS
Спасибо. Буду разбираться.
This is a "lo-fi" version of our main content. To view the full version with more information, formatting and images, please click here.
Powered by DjangoBB