更改应用程序调色板运行时,无需重新启动应用程序

V.K*_*.K. 5 c++ qt

我成功地将黑暗主题用于 Qt5 应用程序的“融合”风格。我想添加切换主题的功能。如果用户需要重新启动应用程序,这没有问题,调色板在应用程序启动时正确初始化。但我希望能够在不重新启动的情况下执行此运行时操作。大多数小部件支持这种可能性,但其他一些小部件(例如QComboBoxQSpinBoxQTreeView)不支持。这可以通过以下代码片段证明 - 只需按下“重置样式”按钮,您就可以看到小部件的某些部分如何正确更改,但其他部分却没有。我在 Windows 10 上使用最新的 Qt 5.10。在我看来,这似乎是 Qt 错误,但有任何解决方法或 hack 吗?

这是我的main.cpp

#include "widget.h"
#include <QApplication>

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);

    // apply the dark color scheme
    qApp->setStyle("fusion");
    QPalette darkPalette;
    darkPalette.setColor(QPalette::Window,QColor(53,53,53));
    darkPalette.setColor(QPalette::WindowText,Qt::white);
    darkPalette.setColor(QPalette::Disabled,QPalette::WindowText,QColor(127,127,127));
    darkPalette.setColor(QPalette::Base,QColor(42,42,42));
    darkPalette.setColor(QPalette::AlternateBase,QColor(66,66,66));
    darkPalette.setColor(QPalette::ToolTipBase,Qt::white);
    darkPalette.setColor(QPalette::ToolTipText,Qt::white);
    darkPalette.setColor(QPalette::Text,Qt::white);
    darkPalette.setColor(QPalette::Disabled,QPalette::Text,QColor(127,127,127));
    darkPalette.setColor(QPalette::Dark,QColor(35,35,35));
    darkPalette.setColor(QPalette::Shadow,QColor(20,20,20));
    darkPalette.setColor(QPalette::Button,QColor(53,53,53));
    darkPalette.setColor(QPalette::ButtonText,Qt::white);
    darkPalette.setColor(QPalette::Disabled,QPalette::ButtonText,QColor(127,127,127));
    darkPalette.setColor(QPalette::BrightText,Qt::red);
    darkPalette.setColor(QPalette::Link,QColor(42,130,218));
    darkPalette.setColor(QPalette::Highlight,QColor(42,130,218));
    darkPalette.setColor(QPalette::Disabled,QPalette::Highlight,QColor(80,80,80));
    darkPalette.setColor(QPalette::HighlightedText,Qt::white);
    darkPalette.setColor(QPalette::Disabled,QPalette::HighlightedText,QColor(127,127,127));
    qApp->setPalette(darkPalette);

    Widget w;
    w.show();

    return a.exec();
}
Run Code Online (Sandbox Code Playgroud)

这是widget.h

#pragma once

#include <QWidget>

class Widget : public QWidget
{
    Q_OBJECT

public:
    explicit Widget(QWidget *parent = 0);

};
Run Code Online (Sandbox Code Playgroud)

widget.cpp

#include "widget.h"

#include <QVBoxLayout>
#include <QComboBox>
#include <QSpinBox>
#include <QTreeWidget>
#include <QPushButton>
#include <QApplication>
#include <QStyleFactory>

Widget::Widget(QWidget *parent) :
    QWidget(parent)
{
    auto layout = new QVBoxLayout(this);
    auto comboBox = new QComboBox();
    auto spinBox = new QSpinBox();
    auto listWidget = new QTreeWidget();
    listWidget->setHeaderLabels(QStringList() << "Column1" << "Column2");
    auto button = new QPushButton("Reset style");

    // reset the palette to the default 'light' color scheme
    connect(button, &QPushButton::clicked, 
            [] { qApp->setPalette(QStyleFactory::create("fusion")->standardPalette()); });

    layout->addWidget(comboBox);
    layout->addWidget(spinBox);
    layout->addWidget(listWidget);
    layout->addWidget(button);
}
Run Code Online (Sandbox Code Playgroud)

这是黑暗的:

在此输入图像描述

重置样式后:

在此输入图像描述

更新:此错误已报告给 Qt 并已修复。干得好,Qt 团队。

Jan*_*ler 1

根据此错误报告中的讨论:https://bugreports.qt.io/browse/QTBUG-65475该问题似乎与某些样式中完成的像素图缓存有关。更改调色板后,不会从全局 QPixmapCache 中清除相应的像素图。

一种可能的解决方法是手动清除完整的 QPixmapCache:

QPixmapCache::clear(); 
Run Code Online (Sandbox Code Playgroud)

如果必须重新计算大量像素图,则会对性能产生明显的影响。