Найти - Пользователи
Полная версия: PyQT и многопоточность
Начало » GUI » PyQT и многопоточность
1 2 3 4 5 6 7
Rodegast
http://python.su/forum/topic/24662/?page=2#post-130903
admiral
Переписал по Вашему примеру.
import time
from PyQt5 import QtCore
from PyQt5.QtCore import Qt
from PyQt5.QtWidgets import QApplication, QWidget, QPushButton, QMessageBox, QDesktopWidget
from PyQt5.QtWidgets import QMainWindow, QLabel, QLineEdit, QGridLayout, QCheckBox
from PyQt5.QtCore import QCoreApplication
from PyQt5.QtGui import QPixmap,QImage
#from threading import Thread #Потоки
class Main_Window(QMainWindow):
    def __init__(self):
        super(Main_Window,self).__init__()
        self.initUI()
        self.t = MyThread()
        QtCore.QObject.connect(self.t, QtCore.SIGNAL("message(str)"), self.setStatusBar)
        self.t.start()
    def initUI(self):
        self.statusBar().showMessage('Ready')
    #Отображаем текст в статусбаре
    def setStatusBar(self,text):
        self.statusBar().showMessage(str(text))
class Main_Widget(QWidget):
    def __init__(self):
        super(Main_Widget,self).__init__()
class MyThread(QtCore.QThread):
    def __init__(self):
         QtCore.QThread.__init__(self)
    def run(self):
        time.sleep(2)
        i = 0
        while True:
            text = str(i)
            i = i+1
            #Тут надо как-то вызвать смену текста статусбара
            self.emit(QtCore.SIGNAL("message(str)"), text)
            time.sleep(2)
if __name__ == '__main__':
    import sys
    app = QApplication(sys.argv)
    window = Main_Window()
    widget = Main_Widget()
    window.setCentralWidget(widget)
    window.show()
    #window.connect(QtCore.pyqtSignal("message()"),window.setStatusBar)
    sys.exit(app.exec_())
Даже QThread начал использовать
Всеравно ругается вот так:
Traceback (most recent call last):
  File "<string>", line 420, in run_nodebug
  File "D:\MyFiles\tests\1.py", line 58, in <module>
    window = Main_Window()
  File "D:\MyFiles\tests\1.py", line 26, in __init__
    QtCore.QObject.connect(self.t, QtCore.SIGNAL("message(str)"), self.setStatusBar)
AttributeError: type object 'QObject' has no attribute 'connect'
так же ругается и в другом месте
Traceback (most recent call last):
  File "D:\MyFiles\tests\1.py", line 52, in run
    self.emit(QtCore.SIGNAL("message(str)"), text)
AttributeError: 'MyThread' object has no attribute 'emit'
admiral
Блина, да что же это за система такая…
Даже просто сменить строку статусбара из другого потока не получается…
Rodegast
# coding: utf-8
import sys
import PySide.QtGui as QtGui
import PySide.QtCore as QtCore
class Main_Window(QtGui.QMainWindow):
    def __init__(self):
        QtGui.QMainWindow.__init__(self)
        self.statusBar().showMessage('Ready')
        self.t = MyThread()
        self.connect(self.t, QtCore.SIGNAL("message(PyObject)"), self.setStatusText)
        self.t.start()
    def setStatusText(self, text):
        self.statusBar().showMessage(text)
class MyThread(QtCore.QThread):
    def __init__(self):
         QtCore.QThread.__init__(self)
    def run(self):
        QtCore.QThread.msleep(2000)
        i = 0
        while True:
            text = str(i)
            i = i+1
            #Тут надо как-то вызвать смену текста статусбара
            self.emit(QtCore.SIGNAL("message(PyObject)"), text)
            QtCore.QThread.msleep(2000)
if __name__ == '__main__':
    app = QtGui.QApplication(sys.argv)
    window = Main_Window()
    window.show()
    sys.exit(app.exec_())
admiral
Спасибо. PySide у меня не установлен. И, как я понял, для PyQt5 не подходит код. Все равно ругается.
Но наконец-то я нашел внятное объяснение как делать сигналы вот тут.
Оказывается нужно сделать отдельный класс с наследованием от QObject, в нем прописать сигнал. И только потом уже можно к этому сигналу делать connect.
Вот в каком случае у меня заработало:
import time
from PyQt5 import QtCore
from PyQt5.QtCore import Qt, QObject, pyqtSignal
from PyQt5.QtWidgets import QApplication, QWidget, QPushButton, QMessageBox, QDesktopWidget
from PyQt5.QtWidgets import QMainWindow, QLabel, QLineEdit, QGridLayout, QCheckBox
from PyQt5.QtCore import QCoreApplication
from PyQt5.QtGui import QPixmap,QImage
from threading import Thread #Потоки
class Main_Window(QMainWindow):
    def __init__(self):
        super(Main_Window,self).__init__()
        self.initUI()
    def initUI(self):
        self.statusBar().showMessage('Ready')
    #Отображаем текст в статусбаре
    def setStatusBar(self,text):
        self.statusBar().showMessage(str(text))
class Main_Widget(QWidget):
    def __init__(self):
        super(Main_Widget,self).__init__()
class MyThread(Thread):
    def __init__(self,f):
        Thread.__init__(self)
        self.f = f
    def run(self):
        time.sleep(2)
        i = 0
        while True:
            text = str(i)
            i = i+1
            #Тут надо как-то вызвать смену текста статусбара
            self.f.message.emit(text)
            time.sleep(2)
class foo(QObject):
    message = pyqtSignal(str)
if __name__ == '__main__':
    import sys
    app = QApplication(sys.argv)
    window = Main_Window()
    widget = Main_Widget()
    window.setCentralWidget(widget)
    window.show()
    f=foo()
    f.message.connect(window.setStatusBar)
    t = MyThread(f)
    t.start()
    sys.exit(app.exec_())
py.user.next
Вот заготовка, которая работает для PyQt4
#!/usr/bin/env python3
 
from PyQt4 import QtGui, QtCore
import sys
import time
 
class MainWindow(QtGui.QMainWindow):
 
    def __init__(self):
        super().__init__()
        self.init_ui()
 
    def init_ui(self):
 
        self.thread = Thread(self)
        self.thread.message[str].connect(self.change_status)
        self.thread.start()
 
        self.statusBar().showMessage('Ready')
        self.show()
 
    def change_status(self, text):
        self.statusBar().showMessage(text)
 
class Thread(QtCore.QThread):
 
    message = QtCore.pyqtSignal(str)
          
    def run(self):
        while True:
            n = int(time.time()) % 10
            self.message.emit(str(n))
            time.sleep(1)
 
def main():
    app = QtGui.QApplication(sys.argv)
    ex = MainWindow()
    sys.exit(app.exec_())
 
if __name__ == '__main__':
    main()

Попробовал поставить PyQt5; короче, не поставилось. Через pip3 тянутся какие-то экзешники виндовые, а из исходников - проблема с qmake. Сырая установка, причём там у них не setup.py, как должно быть, а какой-то configure.py.

Можешь попробовать ещё добавить QObject к базовым классам потока.
class Thread(QtCore.QThread, QtCore.QObject):

admiral
Вот в каком случае у меня заработало:
Слот у тебя неправильно написан. Приходит текст, то есть уже строка, а ты строку снова делаешь строкой.
admiral
py.user.next
Слот у тебя неправильно написан. Приходит текст, то есть уже строка, а ты строку снова делаешь строкой.
Это я для надежности. А то в питоне с переменной можно делать все что угодно, а статусбар только строку может принимать. Ничего же страшного? Или стоит убрать преобразование в строку?
admiral
Блина, буду наверное кодить на PyQT4, а то каждый раз какие-то проблемы, а в инете большинство примеров для PyQT4 и, как оказалось, не так-то просто их переделать.
py.user.next
admiral
А то в питоне с переменной можно делать все что угодно
Она должна выпасть, если что-то не то подаётся.

admiral
Или стоит убрать преобразование в строку?
Снаружи нужно преобразовывать.

admiral
Это я для надежности. :)
Функция становится надёжнее тогда, когда она не делает ничего лишнего - занимается только своим делом. (Функциональная прочность модуля.)
admiral
py.user.next
Вот заготовка, которая работает для PyQt4
Поставил PyQT4 - заработала без проблем и ошибок. И без лишних созданий классов. Спасибо.
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