微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

Qt读取样式表中的动态qproperties

如何解决Qt读取样式表中的动态qproperties

我正在编写一个包含具有不同Qt属性的窗口小部件的应用程序。这些属性之一是简单的颜色属性

Q_PROPERTY(QColor color GET color SET setColor NOTIFY colorChanged)

我希望能够从样式表中访问此属性以更改小部件的外观。 样式表将由用户提供,并且不能在应用程序中动态创建。 我不知道用户想要使应用程序看起来像什么,但是我想给他们机会根据小部件的动态属性设置颜色(和其他属性):

MyWidget {
  border: 1px solid red;
  background-color: <color property value>
}

在颜色方​​面,根据Qt documentation,应通过访问小部件的调色板来实现所需的行为:

MyWidget {
  border: 1px solid red;
  background-color: palette(window);
}

但是,正如许多人已经报告过的那样,这似乎并没有达到预期的效果,因为样式表不会访问小部件自己的调色板,而是访问应用程序调色板。

Qt wiki中所述,可以使用选择器读取或使用qproperty-作为写入前缀来访问动态属性

用于编写自定义属性的样式表如下:

MyWidget {
  border: 1px solid red;
  qproperty-color: red;
}

使用属性选择器读取自定义属性如下:

MyWidget[color="red"] {
  border: 1px solid red;
}

(注意:我不确定这个选择器是否可以正常工作,我还没有尝试过使用颜色)。 现在,如果我有少量可能的颜色,这将适合我的情况。 但是,我的应用程序动态计算颜色,这将导致2 ^ 24(不计算alpha)颜色。

看到可以通过使用qproperty-color: <value>;获得对属性的写访问权,我希望读访问权在语法上是对称的:

MyWidget {
  border: 1px solid red;
  background-color: qproperty-color;
}

但是,这不起作用,因此我在这里发布。

是否有人找到其他方法来访问属性,并在样式表中使用它们来更改小部件的外观,而无需事先知道可能的值?

解决方法

一个月前,我遇到了类似的问题,并且我也尝试使用StyleSheet解决此问题,但最终放弃了将StyleSheet用于QPalette的想法。

使用StyleSheet更改小部件的外观需要进行很多工作,尤其是当小部件的大小可调整时。我建议改用QPalette。但是,使用QPalette有一个陷阱:有些样式,尤其是像window这样的默认样式,不能让您覆盖该样式调色板的所有属性。我建议将应用程序的默认样式更改为fusion并在应用程序中使用其调色板:

#include "mainWindow.h"
#include <QtWidgets/QApplication>
#include <QStyleFactory>
#include "start.h"

int main(int argc,char *argv[])
{
    QApplication::setStyle(QStyleFactory::create("Fusion")); // Setting Fusion Style
    QPalette light = QApplication::palette(); // Getting Fusion Style Palette
    Start S(light); // Making Changes to the palette
    QApplication A(argc,argv);
    mainWindow W(&S,&A); // Passing the palette to main window so that you can change it dynamically
    W.show();
    return A.exec();
}

使用fusion样式有很多优点:

  • 支持定制几乎所有ColorGroupColorRole
  • 有一个黑暗的主题:FusionDarkTheme
  • StyleSheet更容易维护

要更改小部件的背景,您还必须将其autoFillBackground值设置为true,否则其父级的背景将覆盖小部件的背景。这是您无法更改窗口小部件的背景颜色的原因之一。您不必为每个小部件分别进行更改,您可以像这样:

void mainWindow::setAutoBackgroundForWidget()
{
    QList<QWidget *> widgets = this->findChildren<QWidget *>();
    for(QWidget *wid : qAsConst(widgets))
    {
        QList<QByteArray> pro = wid->dynamicPropertyNames();
        if(!pro.isEmpty())
        {
            for(QByteArray byt : qAsConst(pro))
            {
                if(byt == "Level")
                {
                    wid->setAutoFillBackground(true);
                }
            }
        }
    }
}

上面的函数setAutoBackgroundForWidget()是我创建的函数,我在mainWindow的构造函数结束之前调用了该函数。此函数选择所有具有动态属性“ Level”的小部件,使其具有自己的背景,而不使用其父级的背景。您可以相应地修改上述功能,以选择所需的小部件。

完成上述操作后,剩下的就是使用QColorDialog向用户询问他们需要的颜色,复制当前调色板并将其中的给定ColorRole更改为新的调色板。使用setPalette()为新的调色板上色并将其应用于您的小部件。您还可以在mainWindow cpp文件中的单个函数中为所有小部件完成该操作。

对于StyleSheet,我可以确认以下工作:

MyWidget[color="red"] {
border: 1px solid red;
}

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。