首页 > 解决方案 > pyqt5更改按钮随机随机崩溃

问题描述

我想使用递归来改变推送背景。但是 Gui 会随机崩溃。我收到以下消息。“无法解析对象 QPushButton(0x2b04523d9e0) 的样式表”以下是我的代码。包括 2 个文件,一个用于 Gui,另一个用于 Main。

gui_01.py

import ctypes
from PyQt5 import QtCore, QtGui, QtWidgets

class Ui_MainWindow(object):

    def setupUi(self, MainWindow):

        user32 = ctypes.windll.user32
        self.screensize_width = user32.GetSystemMetrics(0)
        self.screensize_height = user32.GetSystemMetrics(1)
        self.rows = (self.screensize_height - 100) // 20
        self.columns = (self.screensize_width - 100) // 20

        MainWindow.setObjectName("MainWindow")
        MainWindow.setGeometry(0, 0, self.screensize_width, self.screensize_height)
        self.centralwidget = QtWidgets.QWidget(MainWindow)
        self.centralwidget.setObjectName("centralwidget")
        MainWindow.setCentralWidget(self.centralwidget)
        self.menubar = QtWidgets.QMenuBar(MainWindow)
        self.menubar.setGeometry(QtCore.QRect(0, 0, 800, 20))
        self.menubar.setObjectName("menubar")
        self.menuFile = QtWidgets.QMenu(self.menubar)
        self.menuFile.setObjectName("menuFile")
        self.menuAuthor = QtWidgets.QMenu(self.menubar)
        self.menuAuthor.setObjectName("menuAuthor")
        MainWindow.setMenuBar(self.menubar)
        self.statusbar = QtWidgets.QStatusBar(MainWindow)
        #self.statusbar.setGeometry(QtCore.QRect(0, self.rows*20, 400, 20))
        self.statusbar.setToolTip("")
        self.statusbar.setWhatsThis("")
        self.statusbar.setAccessibleName("")
        self.statusbar.setAccessibleDescription("")
        self.statusbar.setAutoFillBackground(True)
        self.statusbar.setObjectName("statusbar")
        self.statusbar.setStyleSheet("background-color: red;")
        MainWindow.setStatusBar(self.statusbar)
        self.actionOpen = QtWidgets.QAction(MainWindow)
        self.actionOpen.setObjectName("actionOpen")
        self.actionSave_as = QtWidgets.QAction(MainWindow)
        self.actionSave_as.setObjectName("actionSave_as")
        self.actionLife_game = QtWidgets.QAction(MainWindow)
        self.actionLife_game.setObjectName("actionLife_game")
        self.actionAbout_Author = QtWidgets.QAction(MainWindow)
        self.actionAbout_Author.setObjectName("actionAbout_Author")
        self.menuFile.addAction(self.actionOpen)
        self.menuFile.addAction(self.actionSave_as)
        self.menuAuthor.addAction(self.actionLife_game)
        self.menuAuthor.addSeparator()
        self.menuAuthor.addAction(self.actionAbout_Author)
        self.menubar.addAction(self.menuFile.menuAction())
        self.menubar.addAction(self.menuAuthor.menuAction())

        self.start_button = QtWidgets.QPushButton(self.centralwidget)
        self.start_button.setGeometry(QtCore.QRect(self.screensize_width - 100, (self.rows-5)*20-1, 50, 51))
        self.start_button.setText("Start")
        self.start_button.setStyleSheet("QPushButton{background-color: lightGray;border-width: 4px;border-color: black;font-size: 20px;font-weight:bold; font-family: Roman times;}")

        self.stop_button = QtWidgets.QPushButton(self.centralwidget)
        self.stop_button.setGeometry(QtCore.QRect(self.screensize_width - 50, (self.rows-5)*20-1, 50, 51))
        self.stop_button.setText("Stop")
        self.stop_button.setStyleSheet("QPushButton{background-color: lightGray;border-width: 4px;border-color: red;font-size: 20px;font-weight:bold; font-family: Roman times;}")

        self.clear_button = QtWidgets.QPushButton(self.centralwidget)
        self.clear_button.setGeometry(QtCore.QRect(self.screensize_width - 100, (self.rows-5)*20+50, 101, 51))
        self.clear_button.setText("Clear")
        self.clear_button.setStyleSheet("QPushButton{background-color: lightGray;border-width: 0px;border-color: black;font-size: 20px;font-weight:bold; font-family: Roman times;}")

        self.buttons = [[QtWidgets.QPushButton(self.centralwidget) for j in range(self.columns)] for i in
                        range(self.rows)]
        for i in range(self.rows):
            for j in range(self.columns):
                self.buttons[i][j].setGeometry(QtCore.QRect(j * 20, i * 20, 21, 21))
                self.buttons[i][j].setText("")
                if (i+j)%2 == 0:
                    self.buttons[i][j].setStyleSheet("QPushButton{background-color: blue;border-style: solid;border-width: 1px;border-color: black;}")
                else:
                    self.buttons[i][j].setStyleSheet("QPushButton{background-color: white;border-style: solid;border-width: 1px;border-color: black;}")

        MainWindow.setCentralWidget(self.centralwidget)

        #self.retranslateUi(MainWindow)
        QtCore.QMetaObject.connectSlotsByName(MainWindow)

        MainWindow.showMaximized()

主文件

from PyQt5 import QtWidgets, QtGui, QtCore
from PyQt5.QtGui import QPalette, QBrush
from gui_01 import Ui_MainWindow
import sys
import time
import threading


class MainWindow(QtWidgets.QMainWindow):

    def __init__(self):
        super(MainWindow, self).__init__()
        self.ui = Ui_MainWindow()
        self.ui.setupUi(self)
        self.live_list = []
        self.start_enable = False
        self.stop_enable = False
        self.stop_have = False
        self.red = 0

        self.ui.start_button.clicked.connect(self.start_thread)
        self.ui.stop_button.clicked.connect(self.stop)
        self.ui.clear_button.clicked.connect(self.clear)

        for i in range(self.ui.rows):
            for j in range(self.ui.columns):
                self.ui.buttons[i][j].clicked.connect(lambda state, i=i, j=j: self.action(i, j))
                if (i+j)%2 == 0:
                    self.live_list.append((i, j))

    def start_thread(self):
        if not self.start_enable:
            th1 = threading.Thread(target=self.start, args=())
            th1.setDaemon(True)
            th1.start()
        else:
            pass

    def start(self):
        if not self.stop_enable:
            print("Start")
            self.start_enable = True
            self.stop_have = False
            if len(self.live_list) != 0:
                if self.red == 0:
                    for i in range(len(self.live_list)):
                        self.ui.buttons[self.live_list[i][0]][self.live_list[i][1]].setStyleSheet("QPushButton{background-color: red;border-style: solid;border-width: 1px;border-color: black;}")
                    self.red = 1
                else:
                    for i in range(len(self.live_list)):
                        self.ui.buttons[self.live_list[i][0]][self.live_list[i][1]].setStyleSheet("QPushButton{background-color: green;border-style: solid;border-width: 1px;border-color: black;}")
                        self.red = 0
            time.sleep(0.1)
            if len(self.live_list) == 0:
                self.stop_enable = True

            self.start()
        else:
            print("--------------------------end--------------------------------------")
            self.stop_enable = False
            self.start_enable = False

    def stop(self):
        if not self.stop_have:
            self.stop_enable = True
            self.stop_have = True
        else:
            pass

    def clear(self):
        for i in range(len(self.live_list)):
            self.ui.buttons[self.live_list[i][0]][self.live_list[i][1]].setStyleSheet("QPushButton{background-color: white;border-style: solid;border-width: 1px;border-color: black;}")
        self.live_list = []

    def action(self, i, j):
        if self.ui.buttons[i][j].styleSheet() == "QPushButton{background-color: white;border-style: solid;border-width: 1px;border-color: black;}":
            self.ui.buttons[i][j].setStyleSheet("QPushButton{background-color: blue;border-style: solid;border-width: 1px;border-color: black;}")
            self.live_list.append((i, j))
        else:
            self.ui.buttons[i][j].setStyleSheet("QPushButton{background-color: white;border-style: solid;border-width: 1px;border-color: black;}")
            try:
                self.live_list.remove((i, j))
            except:
                pass


# display main window
if __name__ == '__main__':
    app = QtWidgets.QApplication([])
    window = MainWindow()
    window.show()
    sys.exit(app.exec_())

我不知道为什么代码会崩溃。如果我用 tkinter 替换 pyqt5,代码将正确执行。在我看来,线程有一些问题。但我不确定。我希望有人可以帮助我解决它。谢谢你。

标签: pythonmultithreadingpyqt5

解决方案


绝不应该从另一个线程访问或修改Qt 小部件。

我相信QTimer足以满足您的需要,但我无法对其进行测试,因为您没有提供完全最小的、可重现的示例

class MainWindow(QtWidgets.QMainWindow):

    def __init__(self):
        # ...
        self.timer = QtCore.QTimer()
        self.timer.setInterval(100)
        self.timer.timeout.connect(self.updateButtons)

        self.ui.start_button.clicked.connect(self.timer.start)
        self.ui.stop_button.clicked.connect(self.timer.stop)
        self.ui.clear_button.clicked.connect(self.clear)

    def updateButtons(self):
        if len(self.live_list):
            if self.red == 0:
                for i in range(len(self.live_list)):
                    self.ui.buttons[self.live_list[i][0]][self.live_list[i][1]].setStyleSheet("QPushButton{background-color: red;border-style: solid;border-width: 1px;border-color: black;}")
                self.red = 1
            else:
                for i in range(len(self.live_list)):
                    self.ui.buttons[self.live_list[i][0]][self.live_list[i][1]].setStyleSheet("QPushButton{background-color: green;border-style: solid;border-width: 1px;border-color: black;}")
                    self.red = 0
        else:
            self.timer.stop()

正如我在另一个问题中已经告诉您的那样,我强烈建议您不要使用样式表进行样式比较。


推荐阅读