PyQt5 实现UI界面输入网址,完成抓图,并显示抓取进度,通过QThread 类来实现将耗时操作放在子线程中执行
时间: 2024-03-18 17:40:40 浏览: 16
好的,这是一个关于 PyQt5 的问题,需要使用 QThread 类来实现将耗时操作放在子线程中执行,以下是一个简单的实现过程:
1. 创建 UI 界面,包括一个输入框用于输入网址,一个按钮用于触发抓图操作,以及一个进度条用于显示抓取进度。
2. 创建一个继承自 QThread 的子线程类,用于执行耗时的抓图操作。在该子线程类中,需要定义一个信号用于向主线程发送抓取进度信息。
3. 在主线程中,通过连接子线程的信号和主线程的槽函数,来实现抓取进度的更新。
4. 当用户点击抓图按钮时,启动子线程,并在主线程中启动进度条。
5. 当子线程完成抓图操作时,向主线程发送完成信号,主线程中更新进度条状态,并显示抓取结果。
以下是一个简单的实现代码:
```python
from PyQt5.QtCore import Qt, QThread, pyqtSignal
from PyQt5.QtGui import QPixmap
from PyQt5.QtWidgets import QApplication, QLabel, QLineEdit, QPushButton, QVBoxLayout, QWidget, QProgressBar
import requests
class GrabThread(QThread):
progressChanged = pyqtSignal(int) # 定义一个信号,用于向主线程发送抓取进度信息
def __init__(self, url):
super().__init__()
self.url = url
def run(self):
headers = {'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.3'}
response = requests.get(self.url, headers=headers, stream=True)
total_length = response.headers.get('content-length')
if total_length is None: # 如果无法获取文件大小,就默认为 1MB
total_length = 1024 * 1024
else:
total_length = int(total_length)
downloaded_length = 0
with open('grabbed.jpg', 'wb') as f:
for chunk in response.iter_content(chunk_size=1024):
if not chunk:
break
f.write(chunk)
downloaded_length += len(chunk)
progress = int(downloaded_length / total_length * 100)
self.progressChanged.emit(progress) # 每次更新进度时,向主线程发送信号
class MainWindow(QWidget):
def __init__(self):
super().__init__()
self.url_line_edit = QLineEdit()
self.grab_button = QPushButton('Grab')
self.progress_bar = QProgressBar()
self.image_label = QLabel()
layout = QVBoxLayout()
layout.addWidget(self.url_line_edit)
layout.addWidget(self.grab_button)
layout.addWidget(self.progress_bar)
layout.addWidget(self.image_label)
self.setLayout(layout)
self.grab_button.clicked.connect(self.on_grab_button_clicked)
def on_grab_button_clicked(self):
url = self.url_line_edit.text()
if url:
self.progress_bar.setValue(0)
self.grab_thread = GrabThread(url)
self.grab_thread.progressChanged.connect(self.update_progress_bar) # 连接子线程的信号和主线程的槽函数
self.grab_thread.finished.connect(self.on_grab_thread_finished)
self.grab_thread.start()
def update_progress_bar(self, progress):
self.progress_bar.setValue(progress)
def on_grab_thread_finished(self):
self.progress_bar.setValue(100)
pixmap = QPixmap('grabbed.jpg')
self.image_label.setPixmap(pixmap)
if __name__ == '__main__':
app = QApplication([])
window = MainWindow()
window.show()
app.exec_()
```
在上面的代码中,我们创建了一个继承自 QThread 的 GrabThread 子线程类,用于执行耗时的抓图操作。在该子线程类中,我们定义了一个 progressChanged 信号,用于向主线程发送抓取进度信息。在 run() 方法中,我们使用 requests 库来下载网页内容,并在下载过程中更新进度,并发送 progressChanged 信号。
在主线程中,我们创建了一个 MainWindow 类,该类继承自 QWidget,用于显示 UI 界面。在该类中,我们定义了一个 on_grab_button_clicked() 方法用于响应抓图按钮的点击事件,在该方法中,我们启动 GrabThread 子线程,并连接子线程的 progressChanged 信号和主线程的 update_progress_bar() 槽函数,来实现抓取进度的更新。在 GrabThread 子线程完成抓取操作时,我们向主线程发送 finished 信号,主线程中的 on_grab_thread_finished() 槽函数用于更新进度条状态,并显示抓取结果。