如何实现循环中逐个向QTableWidget添加并实时显示元素?
解决QTableWidget循环中实时添加元素不更新的问题
问题描述
希望通过for循环查找元素,每找到一个就立即添加到QTableWidget并实时显示,但当前代码中所有20个元素都要等循环结束后才会全部显示出来,相关代码如下:
from PyQt5.QtWidgets import QMainWindow, QTableWidgetItem from datetime import datetime, timedelta import random import pytz class MainWindow(QMainWindow): def __init__(self, parent=None): QMainWindow.__init__(self) self.ui = Ui_MainWindow() self.ui.setupUi(self) loadJsonStyle(self, self.ui) self.show() self.is_connected = False self.iq_option = None # BOTON GENERA self.ui.generarBtn.clicked.connect(self.generar_Signals) def generar_Signals(self): if self.is_connected and self.iq_option is not None: open_times = self.iq_option.get_all_open_time() if "binary" in open_times: binary_assets = open_times["turbo"] assets_open = [asset for asset, details in binary_assets.items() if details["open"]] expiration_time = 60 signal = [] last_time = datetime.now() for _ in range(20): symbol = random.choice(assets_open) time_diff = random.randint(4, 11) last_time += timedelta(minutes=time_diff) formatted_time = last_time.strftime("%H:%M") hora_s, minute_s = map(int, formatted_time.split(':')) end_time = datetime.now().replace(hour=hora_s, minute=minute_s, second=0, microsecond=0) start_time = end_time - timedelta(days=1) candles = self.iq_option.get_candles(symbol, expiration_time, 1440, start_time.timestamp()) if candles: last_candle = candles[-1] candle_time_utc = datetime.utcfromtimestamp(last_candle['from']).replace(tzinfo=pytz.utc) local_timezone = pytz.timezone('America/Caracas') candle_time_local = candle_time_utc.astimezone(local_timezone) candle_type = "alcista" if last_candle['open'] < last_candle['close'] else "bajista" type_operation="PUT" if candle_type == "alcista" else "CALL" # Agregar la señal a la tabla self.add_signal_to_table(f"{formatted_time} - {symbol} - {type_operation} - 1M") def add_signal_to_table(self, signal): row_position = self.ui.generaTabla.rowCount() self.ui.generaTabla.insertRow(row_position) # Dividir la señal en partes parts = signal.split('-') # Establecer los datos en las celdas de la fila for column, part in enumerate(parts): item = QTableWidgetItem(part.strip()) self.ui.generaTabla.setItem(row_position, column, item)
问题原因
Qt的GUI运行在单主线程中,generar_Signals方法在主线程执行时,循环会持续占用主线程资源,导致GUI事件循环被阻塞,无法及时刷新界面,所以所有元素要等循环完全结束后才会一次性显示。
解决方案
方案1:强制刷新GUI事件(快速修改)
在每次添加行后,调用QApplication.processEvents()强制处理未完成的GUI事件,让界面实时更新。
修改add_signal_to_table方法:
from PyQt5.QtWidgets import QApplication def add_signal_to_table(self, signal): row_position = self.ui.generaTabla.rowCount() self.ui.generaTabla.insertRow(row_position) # Dividir la señal en partes parts = signal.split('-') # Establecer los datos en las celdas de la fila for column, part in enumerate(parts): item = QTableWidgetItem(part.strip()) self.ui.generaTabla.setItem(row_position, column, item) # 强制处理GUI事件,立即刷新界面 QApplication.processEvents()
优缺点:实现简单,改动量小,但如果循环内的操作(比如get_candles)耗时较长,GUI仍会出现卡顿,因为主线程还是被占用。
方案2:使用子线程分离耗时逻辑(规范做法)
将循环中的耗时操作放到子线程中,通过Qt的信号槽机制通知主线程更新UI,彻底避免阻塞主线程,保证GUI流畅。
步骤1:定义工作线程类
from PyQt5.QtCore import QThread, pyqtSignal class SignalGeneratorThread(QThread): # 定义信号,用于传递生成的信号字符串 signal_generated = pyqtSignal(str) def __init__(self, iq_option, assets_open, parent=None): super().__init__(parent) self.iq_option = iq_option self.assets_open = assets_open self._is_running = True def run(self): expiration_time = 60 last_time = datetime.now() for _ in range(20): if not self._is_running: break symbol = random.choice(self.assets_open) time_diff = random.randint(4, 11) last_time += timedelta(minutes=time_diff) formatted_time = last_time.strftime("%H:%M") hora_s, minute_s = map(int, formatted_time.split(':')) end_time = datetime.now().replace(hour=hora_s, minute=minute_s, second=0, microsecond=0) start_time = end_time - timedelta(days=1) candles = self.iq_option.get_candles(symbol, expiration_time, 1440, start_time.timestamp()) if candles: last_candle = candles[-1] candle_time_utc = datetime.utcfromtimestamp(last_candle['from']).replace(tzinfo=pytz.utc) local_timezone = pytz.timezone('America/Caracas') candle_time_local = candle_time_utc.astimezone(local_timezone) candle_type = "alcista" if last_candle['open'] < last_candle['close'] else "bajista" type_operation = "PUT" if candle_type == "alcista" else "CALL" # 发射信号,将数据传递给主线程 self.signal_generated.emit(f"{formatted_time} - {symbol} - {type_operation} - 1M") # 可选:添加小延迟,避免更新过快 self.msleep(100) def stop(self): self._is_running = False self.wait()
步骤2:修改主线程的generar_Signals方法
def generar_Signals(self): if self.is_connected and self.iq_option is not None: open_times = self.iq_option.get_all_open_time() if "binary" in open_times: binary_assets = open_times["turbo"] assets_open = [asset for asset, details in binary_assets.items() if details["open"]] # 创建工作线程 self.signal_thread = SignalGeneratorThread(self.iq_option, assets_open) # 连接线程信号到UI更新方法 self.signal_thread.signal_generated.connect(self.add_signal_to_table) # 线程结束后自动清理 self.signal_thread.finished.connect(self.signal_thread.deleteLater) # 启动线程 self.signal_thread.start()
优缺点:完全分离耗时逻辑与UI操作,GUI全程流畅无卡顿,是Qt官方推荐的异步处理方式,但需要额外编写线程代码,改动量稍大。
内容的提问来源于stack exchange,提问作者Ferry
相关产品推荐
相关产品推荐

