如何获取QWidget样式表中::hover状态的QPalette颜色?
获取QWidget hover状态下样式表设置的QPalette颜色问题
我编写了一段极简代码,用于打印QSpinBox在默认、hover和disabled状态下的QPalette颜色,但hover状态的颜色无法正确获取。
测试代码
int main(int argc, char *argv[]) { QApplication a(argc, argv); QWidget* widget = new QWidget(); widget->setObjectName("widget"); QSpinBox* spinBox = new QSpinBox(); spinBox->setObjectName("spinBox"); QTextEdit* textEdit = new QTextEdit(); textEdit->setFixedSize(60, 20); QHBoxLayout* layout = new QHBoxLayout(widget); layout->addWidget(spinBox); layout->addWidget(textEdit); // random widget to have something else to grab focus widget->setStyleSheet(R"( #spinBox { background-color: rgba(1, 1, 1, 255); color: rgba(1, 1, 1, 255); } #spinBox::hover { background-color: rgba(2, 2, 2, 255); color: rgba(2, 2, 2, 255); } #spinBox::disabled { background-color: rgba(3, 3, 3, 255); color: rgba(3, 3, 3, 255); } )"); widget->show(); static const auto colorToString = [](const QColor& color) -> QString { return QString("rgba: %1, %2, %3, %4").arg(color.red()).arg(color.green()).arg(color.blue()).arg(color.alpha()); }; static const auto printPallete = [](const QPalette& pal) { #define qq qDebug().noquote().nospace() qq << "\n ------ state ------\n" << pal.currentColorGroup(); qq << "\color\n" << colorToString(pal.color(QPalette::ButtonText)); qq << "\nbackground-color\n" << colorToString(pal.color(QPalette::Window)); }; QObject::connect(new QShortcut(QKeySequence(Qt::Key_F1), widget), &QShortcut::activated, [&] { spinBox->setEnabled(true); printPallete(spinBox->palette()); }); QObject::connect(new QShortcut(QKeySequence(Qt::Key_F2), widget), &QShortcut::activated, [&] { spinBox->setEnabled(false); printPallete(spinBox->palette()); }); return a.exec(); }
测试情况
- 未hover QSpinBox时按F1,输出默认状态的QPalette颜色(rgba:1,1,1,255);
- hover QSpinBox时按F1,输出仍为默认状态颜色,无法获取样式表中设置的rgba:2,2,2,255;
- 按F2禁用QSpinBox时,可正确获取到disabled状态的rgba:3,3,3,255。
问题原因
QWidget的palette()方法返回的是基础状态的调色板,hover属于动态伪状态(临时状态),这类状态的样式表属性不会同步到QPalette中。Qt的样式表和QPalette是两套并行的样式系统:只有disabled这种持久状态会更新到QPalette,而hover这类临时状态的样式仅在绘制阶段生效,不会修改widget的palette对象。
解决方法
方法1:通过QStyle计算指定状态的样式值
利用Qt的样式系统,构造包含hover状态的样式选项,让样式计算对应状态下的属性值,这是官方推荐的标准方式:
// 替换原有F1快捷键的槽函数逻辑 QObject::connect(new QShortcut(QKeySequence(Qt::Key_F1), widget), &QShortcut::activated, [&] { spinBox->setEnabled(true); static const auto colorToString = [](const QColor& color) -> QString { return QString("rgba: %1, %2, %3, %4").arg(color.red()).arg(color.green()).arg(color.blue()).arg(color.alpha()); }; // 构造SpinBox的样式选项,并添加hover状态 QStyleOptionSpinBox opt; spinBox->initStyleOption(&opt); opt.state |= QStyle::State_MouseOver; // 获取hover状态下的background-color和color QColor hoverBg = spinBox->style()->styleSheetProperty(spinBox, "background-color", opt.state); QColor hoverText = spinBox->style()->styleSheetProperty(spinBox, "color", opt.state); qDebug().noquote() << "\n ------ hover state ------"; qDebug().noquote() << "color:" << colorToString(hoverText); qDebug().noquote() << "background-color:" << colorToString(hoverBg); // 同时打印默认状态的palette(可选) qDebug().noquote() << "\n ------ default state ------"; printPallete(spinBox->palette()); });
方法2:手动解析样式表字符串
如果样式表结构简单固定,也可以直接解析样式表文本提取对应伪状态的属性值。但这种方法适应性差,样式表结构变化时需要同步修改解析逻辑:
// 在需要获取hover颜色的地方添加以下代码 QString styleSheet = spinBox->styleSheet(); static const auto colorToString = [](const QColor& color) -> QString { return QString("rgba: %1, %2, %3, %4").arg(color.red()).arg(color.green()).arg(color.blue()).arg(color.alpha()); }; // 正则匹配hover状态的样式 QRegularExpression hoverRegex(R"(#spinBox::hover\s*\{\s*background-color:\s*rgba\((\d+),\s*(\d+),\s*(\d+),\s*(\d+)\);\s*color:\s*rgba\((\d+),\s*(\d+),\s*(\d+),\s*(\d+)\);\s*\})"); QRegularExpressionMatch match = hoverRegex.match(styleSheet); if (match.hasMatch()) { QColor hoverBg( match.captured(1).toInt(), match.captured(2).toInt(), match.captured(3).toInt(), match.captured(4).toInt() ); QColor hoverText( match.captured(5).toInt(), match.captured(6).toInt(), match.captured(7).toInt(), match.captured(8).toInt() ); qDebug().noquote() << "\n ------ parsed hover state ------"; qDebug().noquote() << "color:" << colorToString(hoverText); qDebug().noquote() << "background-color:" << colorToString(hoverBg); }
注意事项
- 优先使用方法1,它能正确处理样式继承、优先级、嵌套等复杂场景;
- 不要尝试通过修改QPalette来同步样式表的hover状态,两套系统设计上相互独立,强行同步会导致样式冲突。
内容的提问来源于stack exchange,提问作者Jabu
相关产品推荐
相关产品推荐

