PySide6中await前设置按钮文本不生效的解决方案
问题原因
你的代码里fetch_request方法使用了同步的requests.get,这个操作会阻塞QtAsyncio的事件循环——事件循环被卡住时,UI更新操作(比如按钮文本修改)会被暂时搁置,必须等同步请求完成后才能执行,所以按钮文本要到API请求结束才会变化。
解决方法
有两种可靠的修复方式,核心都是避免阻塞事件循环:
方案1:使用异步HTTP客户端(推荐)
改用异步IO的aiohttp库替代同步的requests,完全贴合asyncio的设计逻辑,不会阻塞事件循环。
步骤:
- 先安装依赖:
pip install aiohttp - 修改代码如下:
from PySide6.QtWidgets import QApplication, QMainWindow, QPushButton, QLineEdit from PySide6.QtGui import QIcon, QFont, QValidator from PySide6.QtCore import QSize, QPoint, Qt import PySide6.QtAsyncio as QtAsyncio import asyncio import aiohttp # 替换为异步HTTP客户端 class AppWindow(QMainWindow): def __init__(self): super().__init__() self.setWindowTitle('METAR Tool') self.setWindowIcon(QIcon('cloud.ico')) self.setFixedSize(QSize(500, 300)) self.setStyleSheet(""" QPushButton { color: white; background-color: #42baff; border-radius: 5px; } QPushButton:hover, QPushButton:disabled { background-color: #3ca8e6; } QPushButton:pressed { background-color: #005180; } """) self.main_font = QFont('Aptos', 18) self.main_font.setLetterSpacing(QFont.SpacingType(1), 1) self.input = QLineEdit(parent=self) self.input.setFont(self.main_font) self.input.setAlignment(Qt.AlignmentFlag.AlignCenter) self.input.setFixedSize(QSize(400, 60)) self.input.setPlaceholderText('ICAO') self.input.move(QPoint(50, 60)) self.button = QPushButton(parent=self, text='Fetch METAR') self.button.setFont(self.main_font) self.button.setFixedSize(QSize(400, 60)) self.button.move(QPoint(50, 180)) self.button.clicked.connect(lambda: asyncio.ensure_future(self.fetch_process('LKPR'))) async def fetch_process(self, icao): self.setDisabled(True) self.button.setText('Fetching...') # 强制触发UI刷新,确保文本立即更新(可选,异步方案下可省略) QApplication.processEvents() self.response = await self.fetch_request(icao) # 请求完成后恢复按钮文本 self.button.setText('Fetch METAR') self.setDisabled(False) async def fetch_request(self, icao): async with aiohttp.ClientSession() as session: async with session.get(f'https://aviationweather.gov/api/data/metar?ids={icao}&format=json&taf=false&hours=0.5') as resp: return await resp.json() class AppCore(): def __init__(self): self.app = QApplication([]) self.app.setStyle('Breeze') self.window = AppWindow() self.window.show() def run(self): QtAsyncio.run(handle_sigint=True) AppCore().run()
方案2:用线程包装同步请求
如果不想更换HTTP库,可以用asyncio.to_thread把同步的requests.get放到后台线程执行,避免阻塞事件循环:
仅修改fetch_request方法即可:
async def fetch_request(self, icao): import requests # 将同步请求委托给后台线程 resp = await asyncio.to_thread( requests.get, f'https://aviationweather.gov/api/data/metar?ids={icao}&format=json&taf=false&hours=0.5' ) return resp.json()
内容的提问来源于stack exchange,提问作者Person
相关产品推荐
相关产品推荐

