Форум сайта python.su
Здравствуйте. Начал изучать PyQT5 и столкнулся с проблемами.
Пишу тестовую программку, которая должна периодически (раз в секунду, к примеру) долбится на сервер и выводить в статусбаре окна состояние (есть связь или нет связи с сервером)
Проблема в том, что отображение окна идет из основного потока, а стучалку на сервер я запихнул в отдельный поток. Для меня оказалось сюрпризом, что окно я не могу изменять из другого потока.
Нашел статью PyQt: простая работа с потоками, но там под PyQT4.
Что делать? Как можно из отдельного потока менять основное окно?
Офлайн
Там есть сигнал у QtCore.QThread() - finished, его подключаешь к нужному слоту, который вносит изменения. Можно и какой-нибудь специальный сигнал сделать в потоке.
Офлайн
py.user.nextСпасибо.
Там есть сигнал у QtCore.QThread() - finished, его подключаешь к нужному слоту, который вносит изменения. Можно и какой-нибудь специальный сигнал сделать в потоке.
Отредактировано admiral (Май 10, 2015 19:12:05)
Офлайн
admiral
как можно с сигналом передать еще и параметр?
class Thread(QtCore.QThread): message = QtCore.pyqtSignal(str) ... message.emit('text')
Офлайн
Спасибо, сейчас попробую.
А еще вопрос: состояние чекбокса я могу считывать из другого потока, или опять как-то через сигнал его считывать надо?
Офлайн
admiralУ него есть сигнал toggled, который посылает состояние при переключении. Сигнал подключается к слоту родительского виджета, который и делает требуемые действия. Результат этих действий можно проверять снаружи.
состояние чекбокса я могу считывать из другого потока
Отредактировано py.user.next (Май 11, 2015 01:45:49)
Офлайн
Что-то я совсем запутался… никак не могу сообразить как связать сигнал со слотом…
Приведу пример:
class Main_Window(QMainWindow): def __init__(self): super(Main_Window,self).__init__() self.initUI() def initUI(self): self.statusBar().showMessage('Ready') class Main_Widget(QWidget): def __init__(self): super(Main_Widget,self).__init__() self.window = Main_Window() #self.initUI() self.window.setCentralWidget(self) self.window.show() #Отображаем текст в статусбаре def setStatusBar(self,text): self.window.statusBar().showMessage(str(text)) class MyThread(Thread): def __init__(self): Thread.__init__(self) def run(self): time.sleep(5) while True: #Тут надо как-то вызвать смену текста статусбара time.sleep(2) if __name__ == '__main__': import sys app = QApplication(sys.argv) w = Main_Widget() t = MyThread() t.start() sys.exit(app.exec_())
Отредактировано admiral (Май 11, 2015 12:07:43)
Офлайн
QMainWindow на то и главное окно, что оно должно быть на вершине иерархии, чтобы при его закрытии программа завершалась.
У главного окна сделай слот, меняющий его статусную строку.
В потоке сделай сигнал, а в цикле выпусти его.
Присоедини сигнал к слоту там, где создаёшь объект потока.
Офлайн
import time from PyQt5 import QtCore from PyQt5.QtCore import Qt,QObject 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): message = QtCore.pyqtSignal(str) def __init__(self): Thread.__init__(self) def run(self): time.sleep(2) i = 0 while True: text = str(i) i = i+1 #Тут надо как-то вызвать смену текста статусбара self.message.emit(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) t = MyThread() t.start() sys.exit(app.exec_())
Exception in thread Thread-1: Traceback (most recent call last): File "C:\Python33\lib\threading.py", line 637, in _bootstrap_inner self.run() File "D:\MyFiles\tests\1.py", line 50, in run self.message.emit(text) TypeError: pyqtSignal must be bound to a QObject, not 'MyThread'
#window.connect(QtCore.pyqtSignal("message()"),window.setStatusBar)
Traceback (most recent call last): File "<string>", line 420, in run_nodebug File "D:\MyFiles\tests\1.py", line 60, in <module> window.connect(QtCore.pyqtSignal("message()"),window.setStatusBar) AttributeError: 'Main_Window' object has no attribute 'connect'
Отредактировано admiral (Май 11, 2015 14:21:22)
Офлайн
Сейчас попробовал
message = QtCore.pyqtSignal(str)
Traceback (most recent call last): File "C:\Python33\lib\threading.py", line 637, in _bootstrap_inner self.run() File "D:\MyFiles\tests\1.py", line 49, in run message.emit(text) AttributeError: 'PyQt5.QtCore.pyqtSignal' object has no attribute 'emit'
Отредактировано admiral (Май 11, 2015 14:21:37)
Офлайн