В моей программе есть главное окно, и в этом окне он запускает поток для считывания мощности с фотодетектора, затем посылает сигнал, который фиксируется слотом в главном окне, который обновляет основной окно gui.PyQt - Dialog в другом потоке
Тогда у меня есть еще один виджет (назовем его программным виджнем), который появляется из главного окна, которое в основном представляет собой обычный текст, в который пользователь может вставлять команды, чтобы программа выполняла их. Теперь возникает вопрос:
Когда я просто открываю программный виджет с помощью «show», основное окно обновляет фотодетектор. Однако, когда я начинаю выполнение последовательности из виджета программирования, главное окно зависает, и показания фотодетектора останавливаются с ним во время выполнения команд (я думаю, он продолжает читать, потому что находится в другом потоке, но он перестает обновлять gui главного окна).
Мой вопрос: Виджет программирования уже по умолчанию используется в другом потоке, так как главное окно продолжает работать, когда оно выскочит. Итак, почему это (главное окно) зависает, когда виджет программирования находится в цикле?
Вот код Тема:
class PDThread(QtCore.QThread):
valueupdate = QtCore.pyqtSignal(float)
state = 1
def __init__(self, state, port):
QtCore.QThread.__init__(self)
self.photodetector = PM100D()
self.port = port
def run(self):
while True:
try:
self.photodetector.connect(self.port)
break
except:
self.dialog = dialog_classes.DialogPort()
self.dialog.set_instrument('PM100D')
self.dialog.exec_()
ret = self.dialog.pm100d.itemText(self.dialog.pm100d.currentIndex())
if ret == QtGui.QDialog.Accepted:
self.port = str(ret)
else:
self.photodetector.__del__()
self.quit()
return
window.PDState = 1
window.startpd.setText('Stop PD')
while self.state == 1:
time.sleep(0.1)
value = self.photodetector.get_pow()
self.valueupdate.emit(value)
Вот функция, которая создает поток и слот в главном окне:
def ActionConnect_PM100D(self):
if self.PDState == 0:
self.PD = PDThread(self.PDState, self.PDport)
self.PD.valueupdate.connect(self.PDHandler)
self.threads = []
self.threads.append(self.PD)
self.PD.start()
else:
self.PDState = 0
self.PD.state = 0
self.startpd.setText('Start PD')
def PDHandler(self, value):
ref = float(self.refpd.value())
self.outputpd.setText(str(value-ref))
Здесь также в главном окне, функция, создает виджет:
def ActionSetup(self):
self.program = dialog_classes.Programming(self.newport, self.output, self.outputpd)
self.program.show()
Наконец, код виджета:
class Programming(QtGui.QDialog, Ui_Programming_Dialog, gui.MyApp):
def __init__(self, ESP300, output, outputpd):
QtGui.QDialog.__init__(self)
self.setupUi(self)
self.setWindowTitle('Programming Setup')
self.openbuttom.clicked.connect(self.Open)
self.save.clicked.connect(self.Save)
self.execute.clicked.connect(self.Execute)
self.newport = ESP300
self.output = output
self.outputpd = outputpd
def Open(self):
self.fileName = QtGui.QFileDialog.getOpenFileName(self, 'OpenFile', '', '*.txt')
try:
text = open(self.fileName).read()
except:
None
else:
self.program.setPlainText(text)
def Save(self):
self.fileName = QtGui.QFileDialog.getSaveFileName(self, 'Save File', '', '*.txt')
try:
open(self.fileName, 'w').write(str(self.program.toPlainText()))
except:
None
def Execute(self):
text = str(self.program.toPlainText())
lines = text.split('\n')
for line in lines:
arg = []
List = line.split(',')
for word in List:
arg.append(word.strip())
if arg[0].lower() == 'move':
if arg[1].lower() == 'x':
self.newport.move_x(float(arg[2]))
elif arg[1].lower() == 'y':
self.newport.move_y(float(arg[2]))
elif arg[1].lower() == 'z':
self.newport.move_z(float(arg[2]))
elif arg[0].lower() == 'wait':
self.newport.wait()
elif arg[0].lower() == 'home':
self.newport.home()
while True:
try:
self.GetPosition()
except:
time.sleep(0.5)
else:
if self.newport.x == 0 and self.newport.y == 0 and self.newport.z == 0:
break
elif arg[0].lower() == 'power on':
self.newport.power_on(arg[1])
elif arg[0].lower() == 'power off':
self.newport.power_off(arg[1])
elif arg[0].lower() == 'pos':
self.newport.pos_x(arg[1])
self.newport.pos_y(arg[2])
self.newport.pos_z(arg[3])
while True:
try:
self.GetPosition()
except:
time.sleep(0.5)
else:
time.sleep(1)
break
elif arg[0].lower() == 'get pos':
self.GetPosition()
elif arg[0].lower() == 'get error':
self.GetError()
elif arg[0].lower() == 'get pow':
print(self.outputpd.toPlainText())
time.sleep(2)
def closeIt(self):
self.close()
Благодарим вас за поддержку.
Нет 'QWidget'-производный объект не может быть в любом потоке, отличном от основного потока. Ваш код не многопоточен, он просто блокирует пользовательский интерфейс, когда вы находитесь в цикле. Код UI работает, выполняя цикл событий, который отправляет события, когда вы застряли в любых слотах или обработчиках событий, цикл событий не запускается.Инвертируйте поток управления: вместо того, чтобы ждать вещей в цикле, используйте таймер, который каждый раз вызывает ваш код, чтобы читать что-либо или реагировать на новые данные, когда он становится доступным, если вы используете, например. 'QSerialPort'. –
Возможно, вы захотите посмотреть на страницу стека Overflow PyQt [документация по потокам] (http://stackoverflow.com/documentation/pyqt/2775/using-threads-with-pyqt#t=201609200232140019483). –