布局中小部件的哪个样式表选择器?

Posted

技术标签:

【中文标题】布局中小部件的哪个样式表选择器?【英文标题】:Which style sheet selector for widgets in a layout? 【发布时间】:2018-03-14 14:26:31 【问题描述】:

假设我们有一个QFormLayout,其中objectName 设置为"formLayout"。 此布局由两个QLabelQLineEdit 和对象组成:

formLayout = QtGui.QFormLayout()
formLayout.setObjectName("formLayout")

label1 = QtGui.QLabel()    
label2 = QtGui.QLabel()

lineEdit1 = QtGui.QLineEdit()
lineEdit2 = QtGui.QLineEdit()

formLayout.addRow(label1, lineEdit1)
formLayout.addRow(label2, lineEdit2)

现在我想用外部.qss 文件更改formLayoutQLabel's/QLineEdit's 的样式。我希望是这样的:

QFormLayout#formLayout > QLabel, QLineEdit
    /*set some styles for QLabel/QLineEdit in the formLayout*/

不幸的是,这不起作用。我知道我可以将formLayout 中的所有QLabel 设置为相同的对象名称:

label1 = QtGui.setObjectName("formLayoutLabel")    
label2 = QtGui.setObjectName("formLayoutLabel")

并像这样设置他们的风格:

QLabel#formLayoutLabel
    /*set some styles for QLabel in the formLayout*/

我的问题:

如何在不使用对象的情况下更改位于外部 .qss 中的父布局/小部件(例如 formLayout)中特定类型的所有小部件(例如 QLabelQLineEdit)的样式命名属性?

【问题讨论】:

所有布局必须有一个父级,并且该布局内的所有小部件都将自动重新设置为其父级。因此,只需为布局的父级指定一个对象名称,然后在您的全局样式表中您可以使用 #formParent QLabel ... 等。有关其他选项,请参阅:Stylesheet Selector Types。 在我的例子中,层次结构看起来像这样:QDialog -> QVBoxLayout-> QHBoxLayout -> QFormLayout。所以所有布局的父级是QDialog 对吗?为了只修改表单布局的组件,我必须为其添加一个容器小部件,这将导致:QDialog -> QVBoxLayout-> QHBoxLayout -> QWidget -> QFormLayout。我已经对此进行了测试,并且可以正常工作。这是最好的解决方案,还是没有“帮助容器小部件”我可以做得更好。 另一个问题:这种方法是最佳实践吗?或者它们是否应该与上面示例中提到的对象名称相同。基本上:通过相同的父对象与相同的对象名称修改 QWidgets 的样式? 我认为没有任何一种“最佳”解决方案。您只需要选择最适合您当前正在开发的应用程序上下文的一个即可。 【参考方案1】:

QLayout 派生类不是QWidget 派生的,这将它们完全排除在 Qt 样式系统之外。

解决此问题的一种方法是使用小部件支持每个布局,即不要让小部件具有多个布局。这样,属于布局的所有小部件(即标签)也是同一个小部件的子级,您可以在其中注入样式表:

QLabel 
    /*set some styles for QLabel in the formLayout*/

因此,如果您有一个具有四个布局的小部件,您应该在其中放置四个子小部件,并将每个布局放在其中一个内(然后按照您之前排列布局的方式布置小部件)。

另一种解决方法是对小部件进行子类化,并在样式表中按类型名称选择它们。例如,如果您在布局中有 特殊 标签,请使用最简单的QLabel 子类:

class Layout1Label(QtGui.QLabel):

    def __init__(self, parent=None):
        super(Layout1Label, self).__init__(parent)

然后只在布局中添加该类型的标签:

label = Layout1Label()
layout.addWidget(label)

并在样式表中引用它们:

Layout1Label 
    /*set some styles for all labels in layout*/

这应该是有效的,但可能会变得乏味并且需要付出很多努力(您最终可能会得到很多类型,仅用于样式表选择)。

【讨论】:

一个小部件不可能有多个布局。同样,所有布局都必须有一个父级(否则它们包含的小部件不会被布局出来)。布局内的任何小部件都将自动重新设置为布局所设置的任何小部件。因此,布局(及其子布局)中的所有小部件将形成自然层次结构。如果这不是真的。嵌套布局不可能工作,级联样式表也是如此。由此也得出结论,一个小部件不可能属于多个布局。 对不起,一定是文字问题。我的意思是一个小部件可以包含多个布局,而不是小部件自己的布局。使用有关布局的子/父关系术语也可能会产生误导,因为它们不是 Qwidget 子类。 一点也不误导。所有布局类都继承 QObject,所有小部件子类也是如此。所以他们最强调确实形成子/父关系。正如我上面所说,如果不是这样,布局和 qss 就不可能工作。对象层次结构是绝对必要的:这就是为什么布局内的所有小部件都会自动重新设置父级。 它在样式的上下文中具有误导性:是的,有父对象和子对象,但其中一些参与 样式层次结构(小部件),而另一些则不参与(布局)。

以上是关于布局中小部件的哪个样式表选择器?的主要内容,如果未能解决你的问题,请参考以下文章

web前端篇:CSS使用,样式表特征,选择器

样式表与布局

CSS笔记

Qt入门系列开发教程QSSqss选择器

CSS介绍

在 Qt 中为整个小部件设置样式表