Форум сайта python.su
Здравствуйте форумчане.
Собственно решил побаловаться с потоками в PyQt5. Придумал небольшую учебную задачку для себя по данной теме.
Форма авторизации для MySql. Всё стандартно: user - password в QLineEdit, кнопки “connect”, “disconnect” и QLabel сообщающая о статусе соединения. Форма должна проверять возможность соединения с сервером 1 раз в 3 секунды. Для этого я в метод run() класса QThread поместил соединение с БД.
#!/usr/bin/python3 # -*- coding:utf-8 -*- import sys import UI_MainForm from PyQt5.QtWidgets import * from PyQt5.QtGui import * from PyQt5.QtCore import * from PyQt5.QtSql import * class MyThread(QThread): mysignal = pyqtSignal(str) def __init__(self, _user=None, _passwd=None, parent=None): self.user = _user self.passwd = _passwd QThread.__init__(self, parent) def run(self): while True: self.sleep(3) db = QSqlDatabase.addDatabase('QMYSQL') db.setHostName('localhost') db.setDatabaseName('testbase') db.setUserName(self.user) db.setPassword(self.passwd) ok = db.open() if ok: self.mysignal.emit('ok') print('Debug: Connection: Ok') db.close() else: self.mysignal.emit('failed') print('Debug: Connection: Failed ' + db.lastError().text()) class MainForm(QMainWindow, UI_MainForm.Ui_MainWindow): def __init__(self): QMainWindow.__init__(self) self.setupUi(self) self.mythread = MyThread() self.pushButton_quit.clicked.connect(qApp.quit) self.pushButton_connect.clicked.connect(self.connect_db) self.pushButton_disconnect.clicked.connect(self.disconnect_db) self.pushButton_connect.clicked.connect(self.start_thread) self.mythread.mysignal.connect(self.change_label_conn_status, Qt.QueuedConnection) def connect_db(self): db = QSqlDatabase.addDatabase('QMYSQL') db.setHostName('localhost') db.setDatabaseName('testbase') db.setUserName(self.lineEdit_user.text()) db.setPassword(self.lineEdit_passwd.text()) ok = db.open() if ok: self.label_connection_status.setText('Connection status: Ok') QMessageBox.information(self, 'Information', 'Successful database connection') else: self.label_connection_status.setText('Connection status: Failed') QMessageBox.critical(self, 'ERROR!', 'No database connection!') def disconnect_db(self): self.pushButton_connect.setEnabled(True) self.lineEdit_user.setEnabled(True) self.lineEdit_passwd.setEnabled(True) self.lineEdit_user.clear() self.lineEdit_passwd.clear() self.lineEdit_user.setFocus() def change_label_conn_status(self, s): self.label_connection_status.setText('Connection status: ' + s) #текст не меняется def start_thread(self): self.pushButton_connect.setEnabled(False) self.lineEdit_user.setEnabled(False) self.lineEdit_passwd.setEnabled(False) self.mythread = MyThread(self.lineEdit_user.text(), self.lineEdit_passwd.text()) self.mythread.start() if __name__ == '__main__': app = QApplication(sys.argv) win = MainForm() win.show() sys.exit(app.exec_())
Офлайн
Здесь приводил пример использования QThread с отсылкой на бабу.
Отредактировано py.user.next (Ноя. 18, 2019 14:12:04)
Офлайн
cyberaxe77эм-м-м- а что это у вас
1. При дауне MySql, label_connection_status не изменяется на “failed”, хотя в консоль метод run() гадит print('Debug: Connection: Failed ' + db.lastError().text()), как и было задумано. Почему?
self.mythread.mysignal.connect(self.change_label_conn_status, Qt.QueuedConnection)
cyberaxe77очевидно вынести передачу логина-пароля из конструктора като так:
2. Два потока (в конструкторе и в методе start_thread) - бред. Как избавиться от этого бреда? Как сделать правильно?
class MyThread(QThread): mysignal = pyqtSignal(str) def setAuth(self, user=None, passwd=None): self._user = user self._passwd = passwd def run(self): .... db.setUserName(self._user) db.setPassword(self._passwd) ...
cyberaxe77Ну самый простой способ это смотреть открыт ли соответсвующий порт, правда при этом вы не знаете какая именно программа слушает этот порт и работает ли она, а так , кроме как попытаться установить соединение пока никакого иного способа не придумали.
3. Может быть можно как-то иначе реализовать проверку доступности MySql для соединения?
[code python][/code]
Офлайн
Спасибо всем помогающим мне.
Вот “пофиксил”…
Как тебе такое, Илон Маск вам такой “фикс”, уважаемые знатоки?
#!/usr/bin/python3 # -*- coding:utf-8 -*- import sys import UI_MainForm from PyQt5.QtWidgets import * from PyQt5.QtGui import * from PyQt5.QtCore import * from PyQt5.QtSql import * class MyThread(QThread): mysignal = pyqtSignal(str) def __init__(self, _user=None, _passwd=None, parent=None): self.user = _user self.passwd = _passwd QThread.__init__(self, parent) def run(self): while True: self.sleep(3) db = QSqlDatabase.addDatabase('QMYSQL') db.setHostName('localhost') db.setDatabaseName('testbase') db.setUserName(self.user) db.setPassword(self.passwd) ok = db.open() if ok: self.mysignal.emit('Ok') print('Debug: Connection: Ok') db.close() else: self.mysignal.emit('Failed') print('Debug: Connection: Failed ' + db.lastError().text()) class MainForm(QMainWindow, UI_MainForm.Ui_MainWindow): def __init__(self): QMainWindow.__init__(self) self.setupUi(self) self.pushButton_quit.clicked.connect(qApp.quit) self.pushButton_connect.clicked.connect(self.connect_db) self.pushButton_disconnect.clicked.connect(self.disconnect_db) self.pushButton_connect.clicked.connect(self.start_thread) def connect_db(self): db = QSqlDatabase.addDatabase('QMYSQL') db.setHostName('localhost') db.setDatabaseName('testbase') db.setUserName(self.lineEdit_user.text()) db.setPassword(self.lineEdit_passwd.text()) ok = db.open() if ok: self.label_connection_status.setText('Connection status: Ok') QMessageBox.information(self, 'Information', 'Successful database connection') else: self.label_connection_status.setText('Connection status: Failed') QMessageBox.critical(self, 'ERROR!', 'No database connection!') def disconnect_db(self): self.pushButton_connect.setEnabled(True) self.lineEdit_user.setEnabled(True) self.lineEdit_passwd.setEnabled(True) self.lineEdit_user.clear() self.lineEdit_passwd.clear() self.lineEdit_user.setFocus() def change_label_conn_status(self, s): self.label_connection_status.setText('Connection status: ' + s) def start_thread(self): self.pushButton_connect.setEnabled(False) self.lineEdit_user.setEnabled(False) self.lineEdit_passwd.setEnabled(False) self.mythread = MyThread(self.lineEdit_user.text(), self.lineEdit_passwd.text()) self.mythread.mysignal.connect(self.change_label_conn_status, Qt.QueuedConnection) self.mythread.start() if __name__ == '__main__': app = QApplication(sys.argv) win = MainForm() win.show() sys.exit(app.exec_())
Офлайн
PEHDOMТаки у небезизвестных граждан Прохорёнка и Дронова подсмотрен сей код был.
что у вас передается вторым аргументом? откуда вы взяли вообще такой синтаксис?
Офлайн
cyberaxe77хорошо, давайте я поставлю вопрос по другому, зачем вам там Qt.QueuedConnection? чем оно отличается от дефолтного Qt.AutoConnection? Если вы чтото пишете вы должны отдавать себе отчет за что отвечает каждая комманда.
Таки у небезизвестных граждан Прохорёнка и Дронова подсмотрен сей код был.
[code python][/code]
Офлайн
> Здесь приводил пример использования QThread с отсылкой на бабу.
Да хватит уже повторять бред этой бабы!
> что у вас передается вторым аргументом? откуда вы взяли вообще такой синтаксис?
Это норм. он флаги для соединения передаёт, обычно они не нужны но иногда бывают полезными.
> Таки у небезизвестных граждан Прохорёнка и Дронова подсмотрен сей код был.
Не читай его книгу, там на 90% тупой перевод документации.
Офлайн
RodegastХорошая девочка - провела расследование. Хоть какую-то пользу принесла мировому сообществу. Прекрасный подход, где всё работает и метод run() не нужен.
Да хватит уже повторять бред этой бабы!
Отредактировано py.user.next (Ноя. 20, 2019 07:51:06)
Офлайн
> всё работает и метод run() не нужен.
Чем же тебе метод run() не нравится?
Офлайн
Rodegasthttps://doc.qt.io/qt-5/qthread.html#details
Чем же тебе метод run() не нравится?
It is important to remember that a QThread instance lives in the old thread that instantiated it, not in the new thread that calls run(). This means that all of QThread's queued slots and invoked methods will execute in the old thread. Thus, a developer who wishes to invoke slots in the new thread must use the worker-object approach; new slots should not be implemented directly into a subclassed QThread.
Отредактировано py.user.next (Ноя. 20, 2019 13:10:17)
Офлайн