值更改时更改颜色 ComboBox

Change color ComboBox when value change

我在带有 Combobox 的 Pyqt5 中有一个 Table。我的 Combobox 有 2 个值:True 或 False,我想用 2 种不同的颜色更改 Combobox 的颜色:当值为 True -> Green 时,当值为 False -> Red 时。我尝试使用样式表更改颜色,但它只能将整个组合框更改为红色或绿色,如下所示:

如何根据其值更改组合框的 2 种不同颜色?

我的代码如下:

# -*- coding: utf-8 -*-
"""
Created on Tue Oct 27 09:21:24 2020

@author: actnmk
"""

import sys
from PyQt5.QtWidgets import (QWidget, QLabel, QLineEdit, QTextEdit, QGridLayout, QApplication)
import pandas as pd
import numpy as np
import PyQt5 
from PyQt5.QtWidgets import QVBoxLayout, QPushButton, QGroupBox, QHBoxLayout, QMainWindow, QApplication, QLineEdit, QFileDialog,  QTableWidget,QTableWidgetItem, QTableView, QStyledItemDelegate
from PyQt5 import QtCore, QtGui, QtWidgets   
import os
from PyQt5.QtWidgets import (QWidget, QPushButton, QHBoxLayout, QVBoxLayout, QApplication)
from PyQt5.QtGui import QIcon
import re

def dataframe():
    lst = [['tom', 'reacher', 'True'], ['krish', 'pete', 'True'], 
           ['nick', 'wilson', 'True'], ['juli', 'williams', 'True']] 
    df = pd.DataFrame(lst, columns =['FName', 'LName', 'Student?'], dtype = float) 
    return df

class Delegate(QtWidgets.QItemDelegate):
    def __init__(self, owner, choices):
        super().__init__(owner)
        self.items = choices

    def createEditor(self, parent, option, index):
        self.editor = QtWidgets.QComboBox(parent)
        self.editor.currentIndexChanged.connect(self.commit_editor)
        self.editor.addItems(self.items)
        return self.editor    

    def paint(self, painter, option, index):
        value = index.data(QtCore.Qt.DisplayRole)
        style = QtWidgets.QApplication.style()
        opt = QtWidgets.QStyleOptionComboBox()
        opt.text = str(value)
        opt.rect = option.rect
        style.drawComplexControl(QtWidgets.QStyle.CC_ComboBox, opt, painter)
        QtWidgets.QItemDelegate.paint(self, painter, option, index)

    def commit_editor(self):      ####test
        editor = self.sender()
        self.commitData.emit(editor)


    def setEditorData(self, editor, index):
        value = index.data(QtCore.Qt.DisplayRole)
        num = self.items.index(value)
        editor.setCurrentIndex(num)

    def setModelData(self, editor, model, index):
        value = editor.currentText()
        model.setData(index, value, QtCore.Qt.EditRole)

    def updateEditorGeometry(self, editor, option, index):
        editor.setGeometry(option.rect)


class PandasModel(QtCore.QAbstractTableModel):
    def __init__(self, data, parent=None):
        QtCore.QAbstractTableModel.__init__(self, parent)
        self._data = data

    def rowCount(self, parent=None):
        return self._data.shape[0]

    def columnCount(self, parent=None):
        return self._data.shape[2]

    def flags(self, index):
        return QtCore.Qt.ItemIsEditable | QtCore.Qt.ItemIsEnabled | QtCore.Qt.ItemIsSelectable

    def data(self, index, role=QtCore.Qt.DisplayRole):
        if index.isValid():
            if role == QtCore.Qt.DisplayRole:
                return str(self._data.iloc[index.row(), index.column()])
        return None

    def headerData(self, col, orientation, role):
        if orientation == QtCore.Qt.Horizontal and role == QtCore.Qt.DisplayRole:
            return self._data.columns[col]
        return None

    def setData(self, index, value, role=QtCore.Qt.EditRole):
        self._data.iloc[index.row(), index.column()] = value
        return True 

class MyWindow(QWidget):

    def __init__(self):
        super().__init__()
        self.setGeometry(300, 200 ,600, 400)
        self.setWindowTitle('Test')
        self.initUI()


    def show_data(self):
        choices = ['True', 'False']
        self.model = PandasModel(dataframe())
        self.table_data.setModel(self.model)                            
        self.table_data.setItemDelegateForColumn(2, Delegate(self,choices))
        ##make combo boxes editable with a single-click:
        for row in range(5):  
            self.table_data.openPersistentEditor(self.model.index(row, 2))

    def print_data(self):
        print(self.table_data.model()._data)

    def initUI(self):

        welcom = QLabel('Welcome to my app!')

        self.btn_print_data = QPushButton('print data')
        self.btn_print_data.clicked.connect(self.print_data)  ##test

        self.btn_show_table = QPushButton('show data')
        self.btn_show_table.clicked.connect(self.show_data)

        self.table_data = QTableView()
        #self.table_result = QTableView()

        hbox1 = QHBoxLayout()
        hbox1.addWidget(welcom)


        vbox2 = QVBoxLayout()
        vbox2.addWidget(self.btn_show_table)
        vbox2.addWidget(self.btn_print_data) ####test

        vbox3 = QVBoxLayout()
        vbox3.addWidget(self.table_data)
        #vbox3.addWidget(self.table_result)

        hbox2 = QHBoxLayout()
        hbox2.addLayout(vbox2)
        hbox2.addLayout(vbox3)

        vbox1 = QVBoxLayout()
        vbox1.addLayout(hbox1)
        vbox1.addLayout(hbox2)

        self.setLayout(vbox1)
        self.show()
        
style = '''
     


        QComboBox
    {
    background-color : lightgreen;
    }
'''
if __name__ == '__main__':
    app = QApplication(sys.argv)
    app.setStyleSheet(style)
    ex = MyWindow()
    sys.exit(app.exec_())

注意:代码有错误,必须改成:

def columnCount(self, parent=None):
    return self._data.shape[1]

另一方面,解决方案是根据选择更改每个组合框的 Qt 样式表:

def commit_editor(self):
    editor = self.sender()
    color = QtGui.QColor()
    if editor.currentText() == "True":
        color = QtGui.QColor("lightgreen")
    elif editor.currentText() == "False":
        color = QtGui.QColor("red")
    qss = """QComboBox{background-color : %s;}""" % (color.name(),)
    editor.setStyleSheet(qss)
    self.commitData.emit(editor)