Помогите пожалуйста разобраться с PyQt5. Я начал осваивать его пару месяцев назад и не до конца понимаю как работает обработка потоков. В чём проблема: есть библиотека DevMeasMod, в которой имеем 2 класса: DataInput и Device. В классе DataInput создаётся окно для ввода пользователем данных. Я немного сократил исходный код для читаемости, т.к. содержание формы не имеет значения:
class DataInput(QWidget): def __init__(self): super(DataInput, self).__init__() self.initUI() def initUI(self): self.ex_event = False oImage = QImage('/.config/spyder/dna.jpg') sImage = oImage.scaled(QSize(600, 455)) palette = QPalette() palette.setBrush(QPalette.Window, QBrush(sImage)) self.setPalette(palette) self.header1 = QLabel(self) self.header1.setText(u'Информация об эксперименте: ') self.header1.setFont(QFont('Decorative', 14, 70)) self.header2 = QLabel(self) self.header2.setText(u'Параметры процесса: ') self.header2.setFont(QFont('Decorative', 14, 70)) self.empty = QLabel(self) self.empty.setText('') self.nameLabel = QLabel(self) self.nameLabel.setText(u'Эксперимент проводит: ') self.nameLabel.setFont(QFont('Decorative', 12, 60)) self.nameLine = QLineEdit(self) openFile = QAction(QIcon('/.config/spyder /openicon.png'), 'Open', self) openFile.setStatusTip('Open file') openFile.triggered.connect(self.showDialog) chbtn = QPushButton(self) chbtn.setIcon(QIcon('/.config/spyder/openicon.png')) chbtn.setIconSize(QSize(20, 15)) chbtn.clicked.connect(self.showDialog) chbtns = QPushButton(self) chbtns.setIcon(QIcon('/.config/spyder/SaveIcon.png')) chbtns.setIconSize(QSize(20, 15)) chbtns.clicked.connect(self.saveDialog) btn = QPushButton(u'Запуск', self) btn.setAutoDefault(True) btn.setStyleSheet("background-color: #7fc7ff") btn.setFont(QFont('Decorative', 12, 65)) btn.clicked.connect(self.saving) mainwindow = QVBoxLayout() self.setLayout(mainwindow) vertical1 = QHBoxLayout() vertical1.addWidget(self.header1) self.setLayout(vertical1) grid1 = QGridLayout() grid1.addWidget(self.nameLabel, 1, 0) grid1.addWidget(self.nameLine, 1, 1) grid1.addWidget(self.expnameLabel, 2, 0) grid1.addWidget(self.expnameLine, 2, 1) grid1.addWidget(self.expnumbLabel, 3, 0) grid1.addWidget(self.expnumbLine, 3, 1) grid1.addWidget(self.filenameLabel, 4, 0) grid1.addWidget(self.filenameLine, 4, 1) grid1.addWidget(self.savenameLabel, 5, 0) grid1.addWidget(self.savenameLine, 5, 1) grid1.addWidget(chbtn, 4, 2) grid1.addWidget(chbtns, 5, 2) hbox = QHBoxLayout() hbox.addStretch(1) hbox.addWidget(btn) hbox.addStretch(1) mainwindow.addLayout(vertical1) mainwindow.addLayout(grid1) mainwindow.addStretch(1) mainwindow.addLayout(hbox) self.setLayout(hbox) self.setLayout(grid1) self.setToolTip(u'Пожалуйста введите информацию о проводимом эксперименте') self.setWindowFlag(Qt.WindowStaysOnTopHint) self.setFixedSize(600, 455) self.center() self.setWindowTitle(u'Ввод данных') self.show() def center(self): qr = self.frameGeometry() cp = QDesktopWidget().availableGeometry().center() qr.moveCenter(cp) self.move(qr.topLeft()) def showDialog(self): fname = QFileDialog.getOpenFileName(self, 'Open file', '/home/gamma- dna/.config/spyder')[0] self.filenameLine.setText(fname) def saveDialog(self): put = os.getcwd() fname = QFileDialog.getOpenFileName(self, 'Save file', put)[0] self.savenameLine.setText(fname) def saving(self): if (len(self.nameLine.text()) == 0 or len(self.expnameLine.text()) == 0 or len(self.expnumbLine.text()) == 0 or len(self.filenameLine.text()) == 0 or len(self.savenameLine.text()) == 0 or len(self.delayLine.text()) == 0 or len(self.timeLine.text()) == 0): reply = QMessageBox.critical(self, 'Message', u'Заполните пустые поля!!!') reply else: self.myname = self.nameLine.text() self.expname = self.expnameLine.text() self.expnumb = self.expnumbLine.text() self.filename = self.filenameLine.text() self.savename = self.savenameLine.text() self.ex_event = True self.close() def keyPressEvent(self, e): if e.key() == Qt.Key_Escape: self.close() elif e.key() == Qt.Key_Return: self.saving()
В классе Device прописан ряд функций, которые будут работать с данными, введёнными пользователем в форме. Например:
class Device(object): def __init__(self): self.rm = visa.ResourceManager() self.instr = None super(Device, self).__init__() def function1(self): code def function2(self): code def function3(self) code
Эта библиотека будет в дальнейшем использована для написания скриптов. Вот пробный скрипт:
import sys import DevMeasMod as dmm from PyQt5.QtCore import QCoreApplication from PyQt5.QtWidgets import QApplication app = QCoreApplication.instance() if app is None: app = QApplication(sys.argv) data = dmm.DataInput() app.exec_() in = data.Device() in.function3() in.function1() in.function2()
Если в классе DataInput в методе saving прописать self.close(), то по нажатию кнопки “Запуск” форма закрывается и выполняется дальнейший код в виде функций, на этом этапе всё нормально. Однако сейчас появилась задача, заключающаяся в выводе сообщений о состоянии выполнения скрипта и результатов функций в окне, например, в QTextBrowser. При этом код вне окна, то есть идущий после app.exec(), не выполняется без его закрытия, а если прописать этот код до app.exec(), то виснут виджеты окна. Вопрос: можно ли сделать так, чтобы по нажатию кнопки окно не закрывалось, но при этом выполнялся дальнейший код из функций класса Device чтобы выводить результат этих функций в окне? Заранее спасибо за Ваше время.