Qwidget的背景颜色改变时程序随机崩溃

Posted

技术标签:

【中文标题】Qwidget的背景颜色改变时程序随机崩溃【英文标题】:Program randomly crash when background-color of Qwidget changes 【发布时间】:2019-09-04 06:43:19 【问题描述】:

设置背景颜色很好,但我的界面有一个 Qwidget 可以在某个点更改其背景颜色。那会导致程序崩溃,当我注释掉变色代码时崩溃就停止了。

下面这段代码运行一段时间后肯定会崩溃。

import sys
from PySide2.QtWidgets import QWidget,QPushButton,QApplication,QListWidget,QGridLayout,\
QLabel,QMainWindow,QLineEdit,QScrollArea,QVBoxLayout,QMessageBox
from PySide2.QtCore import QTimer,QDateTime,QSize,Qt
from PySide2.QtGui import *
import requests,json
import configparser #
import os
import time
import threading #
from pynput import keyboard #
import requests,json
from math import * 
from functools import partial

class MainWindow(QMainWindow):
    def __init__(self):
        super(MainWindow, self).__init__()
        self.resize(320,100)    
        self.setWindowTitle('aaaa')
        self.setStyleSheet("QMainWindow\
        \
            background-color:white;\
            color:white;\
            margin:0px\
        ")
        self.InitializeWindow()
        self.i=0

    def InitializeWindow(self):
        self.statebar=QWidget(self)
        self.statebar.setGeometry(0, 40, 320, 54)
        print(sys._getframe().f_lineno)
        self.statebar.setStyleSheet("QWidgetbackground-color:#1EC5CD")
        self.th_countdown=threading.Thread(target=self.countdown,args=())
        self.th_countdown.setDaemon(True)
        self.th_countdown.start()

        self.message_main=QLabel(self.statebar)
        self.message_main.setGeometry(150,7,40,37)
        self.message_main.setStyleSheet("background:transparent;color:white;margin:0px;font-size:45px;font-weight:bold")
        self.message_main.setWordWrap(True)
        self.message_main.hide()
        self.message_main.setAlignment(Qt.AlignTop|Qt.AlignLeft)
        self.message_signature=QLabel(self.statebar)
        self.message_signature.setGeometry(50,6,42,42)
        self.message_signature.setScaledContents(True)
        self.message_signature.setStyleSheet("background:transparent")

        self.message_result=QLabel(self.statebar)
        self.message_result.setGeometry(150,6,160,25)
        self.message_result.setStyleSheet("background:transparent;color:white;margin:0px;font-size:24px;font-weight:bold")
        self.message_result.setWordWrap(True)
        self.message_result.hide()
        self.message_detail=QLabel(self.statebar)
        self.message_detail.setGeometry(150,34,160,15)
        self.message_detail.setStyleSheet("background:transparent;color:white;margin:0px;font-size:14px")
        self.message_detail.setWordWrap(True)
        self.message_detail.hide()

    def bind(self, ret):
        self.message_result.show()
        self.message_detail.show()
        self.message_main.hide()
        if(ret%2==0):
            self.statebar.setStyleSheet("QWidgetbackground-color:#1EC5CD") ##FA6400
            self.message_result.setText(str(ret))
            self.message_detail.setText(str(ret))
        else:
            self.statebar.setStyleSheet("QWidgetbackground-color:#FA6400") ##FA6400
            self.message_result.setText(str(ret))
            self.message_detail.setText(str(ret))

    def countdown(self):
        while(1):
            time.sleep(0.2)
            self.i=self.i+1
            self.bind(self.i)

if __name__ == '__main__':
    app = 0
    app = QApplication(sys.argv)
    win = MainWindow()
    #icon = QIcon()
    #icon.addPixmap(QPixmap("./res/mdm.ico"),QIcon.Normal, QIcon.Off)
    #win.setWindowIcon(icon)
    win.show()

    sys.exit(app.exec_())
    pass

有时python会抛出错误消息“无法解析对象的样式表...”,有时它只是崩溃而没有消息。

【问题讨论】:

@eyllanesc 我现在添加最小可重现示例 【参考方案1】:

倒计时方法在您正在修改 GUI 的 GUI 以外的线程上运行,并且该操作不安全,因为 2 个线程无法访问相同的资源,从而导致您指出的问题。解决方案不是直接从另一个线程修改 GUI,而是通过线程安全的信号:

import sys
import time
import threading

from PySide2.QtCore import Qt, Signal, Slot
from PySide2.QtWidgets import QApplication, QLabel, QMainWindow, QWidget


class MainWindow(QMainWindow):
    valueChanged = Signal(int)

    def __init__(self):
        super(MainWindow, self).__init__()
        self.resize(320, 100)
        self.setWindowTitle("aaaa")
        self.setStyleSheet(
            """
            QMainWindow
            
                background-color:white;
                color:white;
                margin:0px
            
            """
        )
        self.InitializeWindow()
        self.i = 0

        self.valueChanged.connect(self.bind)

    def InitializeWindow(self):
        self.statebar = QWidget(self)
        self.statebar.setGeometry(0, 40, 320, 54)
        print(sys._getframe().f_lineno)
        self.statebar.setStyleSheet("QWidgetbackground-color:#1EC5CD")
        self.th_countdown = threading.Thread(target=self.countdown)
        self.th_countdown.setDaemon(True)
        self.th_countdown.start()

        self.message_main = QLabel(self.statebar)
        self.message_main.setGeometry(150, 7, 40, 37)
        self.message_main.setStyleSheet(
            "background:transparent;color:white;margin:0px;font-size:45px;font-weight:bold"
        )
        self.message_main.setWordWrap(True)
        self.message_main.hide()
        self.message_main.setAlignment(Qt.AlignTop | Qt.AlignLeft)
        self.message_signature = QLabel(self.statebar)
        self.message_signature.setGeometry(50, 6, 42, 42)
        self.message_signature.setScaledContents(True)
        self.message_signature.setStyleSheet("background:transparent")

        self.message_result = QLabel(self.statebar)
        self.message_result.setGeometry(150, 6, 160, 25)
        self.message_result.setStyleSheet(
            "background:transparent;color:white;margin:0px;font-size:24px;font-weight:bold"
        )
        self.message_result.setWordWrap(True)
        self.message_result.hide()
        self.message_detail = QLabel(self.statebar)
        self.message_detail.setGeometry(150, 34, 160, 15)
        self.message_detail.setStyleSheet(
            "background:transparent;color:white;margin:0px;font-size:14px"
        )
        self.message_detail.setWordWrap(True)
        self.message_detail.hide()

    @Slot(int)
    def bind(self, ret):
        self.message_result.show()
        self.message_detail.show()
        self.message_main.hide()
        qss = "QWidgetbackground-color:%s" % (
            "#1EC5CD" if ret % 2 == 0 else "#FA6400"
        )
        self.statebar.setStyleSheet(qss)
        self.message_result.setNum(ret)
        self.message_detail.setNum(ret)

    def countdown(self):
        while True:
            time.sleep(0.2)
            self.i += 1
            self.valueChanged.emit(self.i)


if __name__ == "__main__":
    app = QApplication(sys.argv)
    win = MainWindow()
    win.show()
    sys.exit(app.exec_())

【讨论】:

以上是关于Qwidget的背景颜色改变时程序随机崩溃的主要内容,如果未能解决你的问题,请参考以下文章

Android从不同的活动改变背景颜色

从插槽 PyQt 更改背景颜色

CSS如何随机定义网页中的背景颜色

在指定时间随机改变不同按钮的颜色

为自定义 QWidget 设置背景颜色

java 编程 背景颜色的改变