You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何实现循环中逐个向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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.02 08:25:27