值更改时更改颜色组合框

Posted

技术标签:

【中文标题】值更改时更改颜色组合框【英文标题】:Change color ComboBox when value change 【发布时间】:2021-02-09 12:18:51 【问题描述】:

我在 Pyqt5 中有一个带有 Combobox 的表格。我的 Combobox 有 2 个值:True 或 False,我想将 Combobox 的颜色更改为 2 种不同的颜色:当值为 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_())

【问题讨论】:

【参考方案1】:

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

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

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

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 = """QComboBoxbackground-color : %s;""" % (color.name(),)
    editor.setStyleSheet(qss)
    self.commitData.emit(editor)

【讨论】:

以上是关于值更改时更改颜色组合框的主要内容,如果未能解决你的问题,请参考以下文章

如何更改组合框下拉按钮的颜色

使用组合框值更改时的新存储值更新/刷新 dojo 数据网格

更改组合框的背景颜色,它根本不改变颜色

有没有办法更改 Microsoft Access 中下拉列表的组合框按钮的颜色

使用组合框更改值单位时如何更新/转换数字文本框值?基于当前单位的值标准化?

根据组合框选择 C# 更改组合框值