PyQt5条件触发样式表动态更新问题:%RETURN字体仅重启GUI才变色
解决PyQt5交易监控GUI中%RETURN组件字体颜色实时更新问题
问题根源
原代码仅通过定时器更新return_text的文本内容,但未在更新时根据收益值的正负动态修改样式表;同时定时器间隔设置为5毫秒过于频繁,会占用不必要的系统资源。此外TextUpdate类的方法中错误地将实例对象self覆盖为文件内容,属于不良编码习惯。
解决方案步骤
- 修复
TextUpdate类的方法,避免覆盖实例对象self - 创建统一的文本更新函数,在更新
return_text时根据收益值判断并修改样式 - 调整定时器间隔为合理值(如1秒),减少资源消耗
修改后的完整代码
from PyQt5 import QtCore, QtGui, QtWidgets from PyQt5.QtWidgets import QApplication, QMainWindow, QPushButton, QPlainTextEdit, QVBoxLayout, QWidget from PyQt5.QtCore import QProcess import subprocess import sys import datetime current_time = datetime.datetime.now() current_time = current_time.strftime('%Y-%m-%d %H:%M') class TextUpdate(): def watch_list(self): with open(r"C:\Users\Administrator\Desktop\stat_arb\gui\watchlist.txt", 'r') as f: content = f.read() return content def order_history(self): with open(r"C:\Users\Administrator\Desktop\stat_arb\gui\orderhistory.txt", 'r') as f: content = f.read() return content def return_value(self): with open(r"C:\Users\Administrator\Desktop\stat_arb\gui\return.txt", 'r') as f: content = f.read().strip() return content def net_value(self): with open(r"C:\Users\Administrator\Desktop\stat_arb\gui\netvalue.txt", 'r') as f: content = f.read() return content class Ui_MainWindow(object): def setupUi(self, MainWindow): MainWindow.setObjectName("MainWindow") MainWindow.resize(915, 413) MainWindow.setStyleSheet( "background-color: rgb(42, 42 , 42)") self.centralwidget = QtWidgets.QWidget(MainWindow) self.centralwidget.setObjectName("centralwidget") self.p = None self.gridLayout = QtWidgets.QGridLayout(self.centralwidget) self.gridLayout.setObjectName("gridLayout") self.frame = QtWidgets.QFrame(self.centralwidget) self.frame.setStyleSheet( "background-color: rgb(42, 42 , 42)") self.frame.setFrameShape(QtWidgets.QFrame.StyledPanel) self.frame.setFrameShadow(QtWidgets.QFrame.Raised) self.frame.setObjectName("frame") self.frame_2 = QtWidgets.QFrame(self.frame) self.frame_2.setGeometry(QtCore.QRect(20, 30, 411, 221)) self.frame_2.setStyleSheet( "background-color: #202020;\n" "border-radius: 12px") self.frame_2.setFrameShape(QtWidgets.QFrame.StyledPanel) self.frame_2.setFrameShadow(QtWidgets.QFrame.Raised) self.frame_2.setObjectName("frame_2") self.watch_text = QtWidgets.QPlainTextEdit(self.frame_2) self.watch_text.setGeometry(QtCore.QRect(10, 40, 391, 121)) self.watch_text.setMouseTracking(False) self.watch_text.setStyleSheet( "border:0;\n" "font-size: 11px;\n" "color: #9e9e9e") self.watch_text.setBackgroundVisible(False) self.watch_text.setObjectName("watch_text") self.watch_label = QtWidgets.QPlainTextEdit(self.frame_2) self.watch_label.setGeometry(QtCore.QRect(10, 10, 391, 31)) self.watch_label.setStyleSheet( "border:0;\n" "font-size: 10px;\n" "font-weight: bold;\n" "color: #ffffff") self.watch_label.setObjectName("watch_label") self.start_button = QtWidgets.QPushButton(self.frame_2) self.start_button.setGeometry(QtCore.QRect(100, 180, 221, 28)) self.start_button.setStyleSheet( "background-color: #61ac3e;\n" "border-radius: 8px;\n" "font-size: 10px;\n" "font-weight: bold;\n" "color: #ffffff") self.start_button.setObjectName("start_button") self.frame_3 = QtWidgets.QFrame(self.frame) self.frame_3.setGeometry(QtCore.QRect(20, 260, 411, 101)) self.frame_3.setStyleSheet( "background-color: #202020;\n" "border-radius: 12px") self.frame_3.setFrameShape(QtWidgets.QFrame.StyledPanel) self.frame_3.setFrameShadow(QtWidgets.QFrame.Raised) self.frame_3.setObjectName("frame_3") self.output_text = QtWidgets.QPlainTextEdit(self.frame_3) self.output_text.setGeometry(QtCore.QRect(10, 40, 391, 51)) self.output_text.setMouseTracking(False) self.output_text.setStyleSheet( "border:0;\n" "font-size: 11px;\n" "color: #9e9e9e;") self.output_text.setVerticalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOff) self.output_text.setBackgroundVisible(False) self.output_text.setObjectName("output_text") self.output_label = QtWidgets.QPlainTextEdit(self.frame_3) self.output_label.setGeometry(QtCore.QRect(10, 10, 391, 31)) self.output_label.setStyleSheet("border:0;\n" "font-size: 10px;\n" "font-weight: bold;\n" "color: #ffffff") self.output_label.setObjectName("output_label") self.frame_4 = QtWidgets.QFrame(self.frame) self.frame_4.setGeometry(QtCore.QRect(450, 140, 411, 221)) self.frame_4.setStyleSheet( "background-color: #202020;\n" "border-radius: 12px") self.frame_4.setFrameShape(QtWidgets.QFrame.StyledPanel) self.frame_4.setFrameShadow(QtWidgets.QFrame.Raised) self.frame_4.setObjectName("frame_4") self.order_text = QtWidgets.QPlainTextEdit(self.frame_4) self.order_text.setGeometry(QtCore.QRect(10, 40, 391, 161)) self.order_text.setMouseTracking(False) self.order_text.setStyleSheet( "border:0;\n" "font-size: 11px;\n" "color: #9e9e9e") self.order_text.setBackgroundVisible(False) self.order_text.setObjectName("order_text") self.order_label = QtWidgets.QPlainTextEdit(self.frame_4) self.order_label.setGeometry(QtCore.QRect(10, 10, 391, 31)) self.order_label.setStyleSheet( "border:0;\n" "font-size: 10px;\n" "font-weight: bold;\n" "color: #ffffff") self.order_label.setObjectName("order_label") self.frame_5 = QtWidgets.QFrame(self.frame) self.frame_5.setGeometry(QtCore.QRect(450, 30, 411, 101)) self.frame_5.setStyleSheet( "background-color: #202020;\n" "border-radius: 12px") self.frame_5.setFrameShape(QtWidgets.QFrame.StyledPanel) self.frame_5.setFrameShadow(QtWidgets.QFrame.Raised) self.frame_5.setObjectName("frame_5") self.nav_text = QtWidgets.QPlainTextEdit(self.frame_5) self.nav_text.setGeometry(QtCore.QRect(10, 40, 181, 41)) self.nav_text.setMouseTracking(False) self.nav_text.setBackgroundVisible(False) self.nav_text.setObjectName("nav_text") self.nav_text.setStyleSheet( "border:0;\n" "font-size: 24px;\n" "color: #1a62dd") self.nav_label = QtWidgets.QPlainTextEdit(self.frame_5) self.nav_label.setGeometry(QtCore.QRect(10, 10, 181, 31)) self.nav_label.setStyleSheet( "border:0;\n" "font-size: 10px;\n" "font-weight: bold;\n" "color: #ffffff") self.nav_label.setObjectName("nav_label") self.return_text = QtWidgets.QPlainTextEdit(self.frame_5) self.return_text.setGeometry(QtCore.QRect(210, 40, 181, 41)) self.return_text.setMouseTracking(False) self.return_text.setBackgroundVisible(False) self.return_text.setObjectName("return_text") # 初始样式 self.return_text.setStyleSheet( "border:0;\n" "font-size: 24px;\n" "color: #9e9e9e") self.return_label = QtWidgets.QPlainTextEdit(self.frame_5) self.return_label.setGeometry(QtCore.QRect(210, 10, 181, 31)) self.return_label.setStyleSheet( "border:0;\n" "font-size: 10px;\n" "font-weight: bold;\n" "color: #ffffff") self.return_label.setObjectName("return_label") self.gridLayout.addWidget(self.frame, 0, 0, 1, 1) MainWindow.setCentralWidget(self.centralwidget) self.retranslateUi(MainWindow) self.timer = QtCore.QTimer() # 调整定时器间隔为1秒,避免资源浪费 self.timer.start(1000) # 绑定统一的更新函数 self.timer.timeout.connect(self.update_all_texts) self.start_button.pressed.connect(self.start_process) self.output_text.setReadOnly(True) QtCore.QMetaObject.connectSlotsByName(MainWindow) def retranslateUi(self, MainWindow): _translate = QtCore.QCoreApplication.translate MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow")) self.watch_label.setPlainText(_translate("MainWindow", " WATCHLIST")) self.start_button.setText(_translate("MainWindow", "START")) self.output_label.setPlainText(_translate("MainWindow", " OUTPUT")) self.order_label.setPlainText(_translate("MainWindow", " ORDER HISTORY")) self.nav_label.setPlainText(_translate("MainWindow", " NET VALUE")) self.return_label.setPlainText(_translate("MainWindow", " %RETURN")) def message(self, s): self.output_text.appendPlainText(s) def start_process(self): if self.p is None: self.message(f'[STATUS] {current_time} Initializing process...') self.p = QProcess() self.p.readyReadStandardOutput.connect(self.handle_stdout) self.p.readyReadStandardError.connect(self.handle_stderr) self.p.stateChanged.connect(self.handle_state) self.p.finished.connect(self.process_finished) self.p.start(r'C:\Users\Administrator\PycharmProjects\pythonProject\venv\Scripts\python.exe', [r"C:\Users\Administrator\Desktop\stat_arb\31b_aug.py"]) def handle_stderr(self): data = self.p.readAllStandardError() stderr = bytes(data).decode("utf8") self.message(stderr) def handle_stdout(self): data = self.p.readAllStandardOutput() stdout = bytes(data).decode("utf8") self.message(stdout) def handle_state(self, state): states = { QProcess.NotRunning: 'Not running...', QProcess.Starting: 'Starting...', QProcess.Running: 'Running...', } state_name = states[state] self.message(f'[STATUS] {current_time} {state_name}') def process_finished(self): self.message("Process finished.") self.p = None def update_all_texts(self): text_updater = TextUpdate() # 更新其他文本组件 self.watch_text.setPlainText(text_updater.watch_list()) self.order_text.setPlainText(text_updater.order_history()) self.nav_text.setPlainText(text_updater.net_value()) # 更新%RETURN文本并动态修改样式 return_str = text_updater.return_value() self.return_text.setPlainText(return_str) # 判断收益值正负,修改字体颜色 try: return_val = float(return_str.replace('%', '')) if return_val > 0: # 正收益设为绿色 self.return_text.setStyleSheet( "border:0;\n" "font-size: 24px;\n" "color: #61ac3e" ) elif return_val < 0: # 负收益设为红色 self.return_text.setStyleSheet( "border:0;\n" "font-size: 24px;\n" "color: #ff4444" ) else: # 零收益恢复默认灰色 self.return_text.setStyleSheet( "border:0;\n" "font-size: 24px;\n" "color: #9e9e9e" ) except ValueError: # 无法转换为数值时保持默认样式 self.return_text.setStyleSheet( "border:0;\n" "font-size: 24px;\n" "color: #9e9e9e" ) def get_termi_futu(): subprocess.call("taskkill /F /IM FutuOpenD.exe") print('[DISCONNECTED]', current_time, ' Connection status. Trading account is disconnected.') if __name__ == "__main__": import sys app = QtWidgets.QApplication(sys.argv) MainWindow = QtWidgets.QMainWindow() ui = Ui_MainWindow() ui.setupUi(MainWindow) MainWindow.show() app.exec_() get_termi_futu()
关键修改说明
- 修复TextUpdate类:将方法中覆盖
self的错误改为使用局部变量content,同时改用with语句管理文件,确保文件正确关闭。 - 统一更新函数:创建
update_all_texts函数,替代多个lambda表达式,集中处理所有文本组件的更新逻辑,便于维护。 - 动态样式修改:在更新
return_text时,尝试将文本转换为数值,根据正负设置不同的字体颜色(正收益绿色、负收益红色、零收益灰色),无法转换时保持默认样式。 - 调整定时器间隔:将原5毫秒的间隔改为1000毫秒(1秒),减少系统资源占用,同时满足实时更新需求。
内容的提问来源于stack exchange,提问作者ms mavie
相关产品推荐
相关产品推荐

