问题描述
我是 GUI 编程的新手,需要有关 QThread 应用程序的帮助。我有一个 gui 程序,可以进行查询并在屏幕上列出查询的结果。我希望在屏幕上的列表完成后打开一个信息对话框。我为此编写了一个函数,当操作成功时,它可以正常工作。但是我无法弄清楚如果出现无效链接条目时如何显示错误对话框。感谢您的帮助。
-我已经注释掉了一些我尝试过但失败的方法。
import sys
import requests
from PyQt5 import QtCore,QtGui,QtWidgets
from PyQt5.QtCore import QThread
from PyQt5.QtWidgets import QMainWindow,QApplication,QMessageBox
from bs4 import BeautifulSoup
from time import sleep
class Ui_MainWindow(object):
def setupUi(self,MainWindow):
MainWindow.setobjectName("MainWindow")
MainWindow.resize(476,391)
self.centralwidget = QtWidgets.QWidget(MainWindow)
self.centralwidget.setobjectName("centralwidget")
self.pushButton = QtWidgets.QPushButton(self.centralwidget)
self.pushButton.setGeometry(QtCore.QRect(0,270,471,81))
self.pushButton.setobjectName("pushButton")
self.lineEdit = QtWidgets.QLineEdit(self.centralwidget)
self.lineEdit.setGeometry(QtCore.QRect(0,31))
self.lineEdit.setobjectName("lineEdit")
self.listWidget = QtWidgets.QListWidget(self.centralwidget)
self.listWidget.setGeometry(QtCore.QRect(0,50,192))
self.listWidget.setobjectName("listWidget")
MainWindow.setCentralWidget(self.centralwidget)
self.menubar = QtWidgets.QMenuBar(MainWindow)
self.menubar.setGeometry(QtCore.QRect(0,476,21))
self.menubar.setobjectName("menubar")
MainWindow.setMenuBar(self.menubar)
self.statusbar = QtWidgets.QStatusBar(MainWindow)
self.statusbar.setobjectName("statusbar")
MainWindow.setStatusBar(self.statusbar)
self.retranslateUi(MainWindow)
QtCore.QMetaObject.connectSlotsByName(MainWindow)
self.running = False
self.pushButton.clicked.connect(self.startBs4Worker)
def retranslateUi(self,MainWindow):
_translate = QtCore.QCoreApplication.translate
MainWindow.setwindowTitle(_translate("MainWindow","MainWindow"))
self.pushButton.setText(_translate("MainWindow","GET"))
def reveiceData(self,data):
# This method is the method that will
# process the data sent by the thread.
if data == None:
return
_translate = QtCore.QCoreApplication.translate
item = QtWidgets.QListWidgetItem()
font = QtGui.QFont()
font.setFamily("Arial")
font.setPointSize(11)
item.setFont(font)
item.setCheckState(QtCore.Qt.Checked)
item.setText(_translate("MainWindow",data))
self.listWidget.addItem(item)
def setThreadStatus(self):
self.running = not self.running
def startBs4Worker(self):
if self.running:
print("Thread is still running ...")
return
else:
self.thread = QThread()
# We send the URL address that the thread will process as a parameter.
self.worker = Bs4Worker(url=self.lineEdit.text())
self.worker.movetoThread(self.thread)
self.thread.started.connect(self.worker.run)
self.worker.finished.connect(self.thread.quit)
self.worker.finished.connect(self.worker.deleteLater)
self.worker.finished.connect(self.setThreadStatus)
self.thread.finished.connect(self.thread.deleteLater)
self.worker.notifyProgress.connect(self.reveiceData)
self.worker.finished.connect(self.uyariBox) #---> With this place active,I Couldn't figure out how to activate the Error message when wrong connection was entered.
self.running = True
self.thread.start()
def uyariBox(self):
self.msg = QMessageBox()
self.msg.thread()
self.msg.setwindowTitle("Bilgi !")
self.msg.setText("Tüm Sonuçlar Getirildi")
self.msg.setIcon(QMessageBox.information)
self.msg.exec_()
class Bs4Worker(QThread):
notifyProgress = QtCore.pyqtSignal(str)
def __init__(self,url,parent=None):
QThread.__init__(self,parent)
self.url = url
def run(self):
try:
r = requests.get(self.url)
soup = BeautifulSoup(r.content)
linkler = soup.find_all("a")
for link in linkler:
baslik = link.get("title")
# Sending header information to master class
self.notifyProgress.emit(baslik)
self.finished.connect(ui.uyariBox) #---> When you activate this place,the warning appears instantly and disappears immediately.
#---> and there is no click anywhere in the app. (Since completion is not pressed in the warning message)
self.finished.emit()
# self.finished.connect(ui.uyariBox) #----> Warning does not appear when you activate this place.
except:
print("link error")
self.finished.emit()
# When I create a new QMessageBox to show the error message,the application crashes.
Uygulama = QApplication(sys.argv)
menu = QMainWindow()
ui = Ui_MainWindow()
ui.setupUi(menu)
menu.show()
sys.exit(Uygulama.exec_())
解决方法
您可以将运算结果作为字符串传递给 uyariBox
方法。
首先,您可以在 Bs4Worker
中创建另一个信号:
class Bs4Worker(QThread):
result = QtCore.pyqtSignal(str)
将之前的 worker.finished
连接更改为 worker.result
:
def startBs4Worker(self):
else:
self.worker.result.connect(self.uyariBox)
#Previous was self.worker.finished.connect(self.uyariBox)
向函数添加变量:
def uyariBox(self,message):
self.msg = QMessageBox()
self.msg.thread()
self.msg.setWindowTitle("Bilgi !")
self.msg.setText(message)
self.msg.setIcon(QMessageBox.Information)
self.msg.exec_()
然后使用信号传递操作的结果:
def run(self):
try:
self.result.emit("Tüm Sonuçlar Getirildi")
except Exception as e:
self.result.emit(f"Error: {e}")
完整代码:
import sys
import requests
from PyQt5 import QtCore,QtGui,QtWidgets
from PyQt5.QtCore import QThread,pyqtSignal
from PyQt5.QtWidgets import QMainWindow,QApplication,QMessageBox
from bs4 import BeautifulSoup
from time import sleep
class Ui_MainWindow(object):
def setupUi(self,MainWindow):
MainWindow.setObjectName("MainWindow")
MainWindow.resize(476,391)
self.centralwidget = QtWidgets.QWidget(MainWindow)
self.centralwidget.setObjectName("centralwidget")
self.pushButton = QtWidgets.QPushButton(self.centralwidget)
self.pushButton.setGeometry(QtCore.QRect(0,270,471,81))
self.pushButton.setObjectName("pushButton")
self.lineEdit = QtWidgets.QLineEdit(self.centralwidget)
self.lineEdit.setGeometry(QtCore.QRect(0,31))
self.lineEdit.setObjectName("lineEdit")
self.listWidget = QtWidgets.QListWidget(self.centralwidget)
self.listWidget.setGeometry(QtCore.QRect(0,50,192))
self.listWidget.setObjectName("listWidget")
MainWindow.setCentralWidget(self.centralwidget)
self.menubar = QtWidgets.QMenuBar(MainWindow)
self.menubar.setGeometry(QtCore.QRect(0,476,21))
self.menubar.setObjectName("menubar")
MainWindow.setMenuBar(self.menubar)
self.statusbar = QtWidgets.QStatusBar(MainWindow)
self.statusbar.setObjectName("statusbar")
MainWindow.setStatusBar(self.statusbar)
self.retranslateUi(MainWindow)
QtCore.QMetaObject.connectSlotsByName(MainWindow)
self.running = False
self.pushButton.clicked.connect(self.startBs4Worker)
def retranslateUi(self,MainWindow):
_translate = QtCore.QCoreApplication.translate
MainWindow.setWindowTitle(_translate("MainWindow","MainWindow"))
self.pushButton.setText(_translate("MainWindow","GET"))
def reveiceData(self,data):
# This method is the method that will
# process the data sent by the thread.
if data == None:
return
_translate = QtCore.QCoreApplication.translate
item = QtWidgets.QListWidgetItem()
font = QtGui.QFont()
font.setFamily("Arial")
font.setPointSize(11)
item.setFont(font)
item.setCheckState(QtCore.Qt.Checked)
item.setText(_translate("MainWindow",data))
self.listWidget.addItem(item)
def setThreadStatus(self):
self.running = not self.running
def startBs4Worker(self):
if self.running:
print("Thread is still running ...")
return
else:
self.thread = QThread()
# We send the URL address that the thread will process as a parameter.
self.worker = Bs4Worker(url=self.lineEdit.text())
self.worker.moveToThread(self.thread)
self.thread.started.connect(self.worker.run)
self.worker.finished.connect(self.thread.quit)
self.worker.finished.connect(self.worker.deleteLater)
self.worker.finished.connect(self.setThreadStatus)
self.thread.finished.connect(self.thread.deleteLater)
self.worker.notifyProgress.connect(self.reveiceData)
self.worker.result.connect(
self.uyariBox) # ---> With this place active,I couldn't figure out how to activate the Error message when wrong connection was entered.
self.running = True
self.thread.start()
def uyariBox(self,message):
self.msg = QMessageBox()
self.msg.thread()
self.msg.setWindowTitle("Bilgi !")
self.msg.setText(message)
self.msg.setIcon(QMessageBox.Information)
self.msg.exec_()
class Bs4Worker(QThread):
result = QtCore.pyqtSignal(str)
notifyProgress = QtCore.pyqtSignal(str)
def __init__(self,url,parent=None):
QThread.__init__(self,parent)
self.url = url
def run(self):
try:
r = requests.get(self.url)
soup = BeautifulSoup(r.content)
linkler = soup.find_all("a")
for link in linkler:
baslik = link.get("title")
# Sending header information to master class
self.notifyProgress.emit(baslik)
self.finished.connect(
ui.uyariBox) # ---> When you activate this place,the warning appears instantly and disappears immediately.
# ---> and there is no click anywhere in the app. (Since completion is not pressed in the warning message)
self.finished.emit()
self.result.emit("Tüm Sonuçlar Getirildi")
# self.finished.connect(ui.uyariBox) #----> Warning does not appear when you activate this place.
except Exception as e:
print("link error")
self.finished.emit()
self.result.emit(f"Error: {e}")
# When I create a new QMessageBox to show the error message,the application crashes.
Uygulama = QApplication(sys.argv)
menu = QMainWindow()
ui = Ui_MainWindow()
ui.setupUi(menu)
menu.show()
sys.exit(Uygulama.exec_())