警告

本节包含从C++自动翻译到Python的代码片段,可能存在错误。

Qt样式表实例#

现在我们将看到一些例子,以了解如何开始使用Qt样式表。

样式表用法#

自定义前景色和背景颜色#

让我们先设置黄色作为应用程序中所有 QLineEdit 的背景颜色。这可以通过以下方式实现

qApp.setStyleSheet("QLineEdit { background-color: yellow }")

如果我们想让属性仅适用于特定对话框的子代(或孙代或曾孙代)QLineEdit,我们会这样做

myDialog.setStyleSheet("QLineEdit { background-color: yellow }")

如果我们只想将属性应用于一个特定的 QLineEdit,我们可以使用 QObject::setObjectName() 为它设置一个名称,然后使用ID选择器来引用它

myDialog.setStyleSheet("QLineEdit#nameEdit { background-color: yellow }")

或者,我们可以在 background-color 属性上直接设置 QLineEdit,省略选择器

nameEdit.setStyleSheet("background-color: yellow")

为了确保良好的对比度,我们也应该指定一个合适的文本颜色

nameEdit.setStyleSheet("color: blue; background-color: yellow")

改变选中文本使用的颜色可能也是一个好主意

nameEdit.setStyleSheet("color: blue;"
                        "background-color: yellow;"
                        "selection-color: yellow;"
                        "selection-background-color: blue;")

使用动态属性进行自定义#

有许多情况下,我们需要展示一个包含必填字段的表格。为了向用户表明该字段是必填的,一个有效(尽管在美学上可疑)的解决方案是使用黄色作为这些字段的背景颜色。结果显示,使用Qt样式表来实现这一点非常容易。首先,我们会使用以下全局样式表

*[mandatoryField="true"] { background-color: yellow }

这意味着任何其 mandatoryField Qt 属性设置为 true 的小部件都将有一个黄色的背景。

然后,对于每个必填字段小部件,我们只需动态创建一个 mandatoryField 属性并设置为 true。例如

nameEdit = QLineEdit(self)
nameEdit.setProperty("mandatoryField", True)
emailEdit = QLineEdit(self)
emailEdit.setProperty("mandatoryField", True)
ageSpinBox = QSpinBox(self)
ageSpinBox.setProperty("mandatoryField", True)

使用盒模型自定义 QPushButton#

这次,我们将展示如何创建一个红色 QPushButton 。这个 QPushButton 可能会连接到一个非常有破坏性的代码片段。

首先,我们想要使用下面的样式表

QPushButton#evilButton { background-color: red }

然而,结果是一个无聊的、没有边框的平面按钮

../_images/stylesheet-redbutton1.png

发生了以下情况

  • 我们提出了一个无法仅使用原生样式满足的请求(例如,Windows Vista主题引擎不允许我们指定按钮的背景颜色)。

  • 因此,按钮是通过样式表渲染的。

  • 我们没有指定 border-widthborder-style 的任何值,所以默认情况下我们获得一个宽度为 0 像素、样式为 none 的边框。

让我们通过指定一个边框来改善情况

QPushButton#evilButton {
    background-color: red;
    border-style: outset;
    border-width: 2px;
    border-color: beige;
}
../_images/stylesheet-redbutton2.png

看起来已经好多了。但按钮显得有点拥挤。让我们使用 padding 在边框和文本之间指定一些间距。此外,我们将强制设置最小宽度,使角落圆润,并指定一个更大的字体以使按钮看起来更美观

QPushButton#evilButton {
    background-color: red;
    border-style: outset;
    border-width: 2px;
    border-radius: 10px;
    border-color: beige;
    font: bold 14px;
    min-width: 10em;
    padding: 6px;
}
../_images/stylesheet-redbutton3.png

唯一剩下的问题是,按钮在我们按下它时没有反应。我们可以通过指定稍有不同的背景颜色并使用不同的边框样式来修复这个问题。

QPushButton#evilButton {
    background-color: red;
    border-style: outset;
    border-width: 2px;
    border-radius: 10px;
    border-color: beige;
    font: bold 14px;
    min-width: 10em;
    padding: 6px;
}
QPushButton#evilButton:pressed {
    background-color: rgb(224, 0, 0);
    border-style: inset;
}

定制 QPushButton 的菜单指示器子控件#

子控件可以访问小部件的子元素。例如,一个与菜单关联的 QPushButton(使用 setMenu() )有一个菜单指示器。让我们定制红色按钮的菜单指示器

QPushButton#evilButton::menu-indicator {
    image: url(myindicator.png);
}

默认情况下,菜单指示器位于填充矩形的底右角。我们可以通过指定 subcontrol-positionsubcontrol-origin 来改变位置以锚定指示器。我们还可以使用 topleft 将指示器移动几个像素。例如

QPushButton::menu-indicator {
    image: url(myindicator.png);
    subcontrol-position: right center;
    subcontrol-origin: padding;
    left: -2px;
}

这将 myindicator.png 定位到 QPushButton 的填充矩形的右中央(有关更多信息,请参阅 subcontrol-origin)。

复杂选择器示例#

由于红色似乎是我们最喜欢的颜色,让我们通过设置以下应用程序范围的样式表将 QLineEdit 中的文本设为红色:

QLineEdit { color: red }

然而,我们希望能够通过将其显示为灰色来提供一个视觉指示,表明一个QLineEdit是只读的

QLineEdit { color: red }
QLineEdit[readOnly="true"] { color: gray }

在某个时候,我们的设计团队提出要求,所有注册表单(对象名称为registrationDialogQLineEdit)都应该呈现棕色

QLineEdit { color: red }
QLineEdit[readOnly="true"] { color: gray }
#registrationDialog QLineEdit { color: brown }

经过几次UI设计会议后,我们决定,所有我们的QDialog都应具有棕色的QLineEdit

QLineEdit { color: red }
QLineEdit[readOnly="true"] { color: gray }
QDialog QLineEdit { color: brown }

问题:如果我们在一个QDialog中有一个只读的QLineEdit会发生什么?[提示:上述冲突解决部分解释了在这种情况下会发生什么。]

特定小部件的自定义#

本节提供使用样式表定制特定小部件的示例。

自定义QAbstractScrollArea#

任何QAbstractScrollArea(项视图、QTextEditQTextBrowser的)背景可以通过背景属性来设置。例如,为了设置随滚动条滚动的背景图像

QTextEdit, QListView {
    background-color: white;
    background-image: url(draft.png);
    background-attachment: scroll;
}

如果背景图像要固定在视口中

QTextEdit, QListView {
    background-color: white;
    background-image: url(draft.png);
    background-attachment: fixed;
}

自定义QCheckBox#

QCheckBox的样式与QRadioButton的样式几乎相同。主要区别是一个三态的QCheckBox有一个不确定状态。

QCheckBox {
    spacing: 5px;
}

QCheckBox::indicator {
    width: 13px;
    height: 13px;
}

QCheckBox::indicator:unchecked {
    image: url(:/images/checkbox_unchecked.png);
}

QCheckBox::indicator:unchecked:hover {
    image: url(:/images/checkbox_unchecked_hover.png);
}

QCheckBox::indicator:unchecked:pressed {
    image: url(:/images/checkbox_unchecked_pressed.png);
}

QCheckBox::indicator:checked {
    image: url(:/images/checkbox_checked.png);
}

QCheckBox::indicator:checked:hover {
    image: url(:/images/checkbox_checked_hover.png);
}

QCheckBox::indicator:checked:pressed {
    image: url(:/images/checkbox_checked_pressed.png);
}

QCheckBox::indicator:indeterminate:hover {
    image: url(:/images/checkbox_indeterminate_hover.png);
}

QCheckBox::indicator:indeterminate:pressed {
    image: url(:/images/checkbox_indeterminate_pressed.png);
}

自定义QComboBox#

我们将查看一个示例,其中QComboBox的下拉按钮看起来是与组合框框架“合并”的。

QComboBox {
    border: 1px solid gray;
    border-radius: 3px;
    padding: 1px 18px 1px 3px;
    min-width: 6em;
}

QComboBox:editable {
    background: white;
}

QComboBox:!editable, QComboBox::drop-down:editable {
     background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1,
                                 stop: 0 #E1E1E1, stop: 0.4 #DDDDDD,
                                 stop: 0.5 #D8D8D8, stop: 1.0 #D3D3D3);
}

/* QComboBox gets the "on" state when the popup is open */
QComboBox:!editable:on, QComboBox::drop-down:editable:on {
    background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1,
                                stop: 0 #D3D3D3, stop: 0.4 #D8D8D8,
                                stop: 0.5 #DDDDDD, stop: 1.0 #E1E1E1);
}

QComboBox:on { /* shift the text when the popup opens */
    padding-top: 3px;
    padding-left: 4px;
}

QComboBox::drop-down {
    subcontrol-origin: padding;
    subcontrol-position: top right;
    width: 15px;

    border-left-width: 1px;
    border-left-color: darkgray;
    border-left-style: solid; /* just a single line */
    border-top-right-radius: 3px; /* same radius as the QComboBox */
    border-bottom-right-radius: 3px;
}

QComboBox::down-arrow {
    image: url(/usr/share/icons/crystalsvg/16x16/actions/1downarrow.png);
}

QComboBox::down-arrow:on { /* shift the arrow when popup is open */
    top: 1px;
    left: 1px;
}

《QComboBox》弹出的窗口是一个QAbstractItemView,并且使用子类选择器进行样式化。

QComboBox QAbstractItemView {
    border: 2px solid darkgray;
    selection-background-color: lightgray;
}

自定义QDockWidget#

可以按以下方式自定义QDockWidget的标题栏和按钮

QDockWidget {
    border: 1px solid lightgray;
    titlebar-close-icon: url(close.png);
    titlebar-normal-icon: url(undock.png);
}

QDockWidget::title {
    text-align: left; /* align the text to the left */
    background: lightgray;
    padding-left: 5px;
}

QDockWidget::close-button, QDockWidget::float-button {
    border: 1px solid transparent;
    background: darkgray;
    padding: 0px;
}

QDockWidget::close-button:hover, QDockWidget::float-button:hover {
    background: gray;
}

QDockWidget::close-button:pressed, QDockWidget::float-button:pressed {
    padding: 1px -1px -1px 1px;
}

如果想让码头的小部件按钮向左移动,可以使用以下样式表

QDockWidget {
    border: 1px solid lightgray;
    titlebar-close-icon: url(close.png);
    titlebar-normal-icon: url(float.png);
}

QDockWidget::title {
    text-align: left;
    background: lightgray;
    padding-left: 35px;
}

QDockWidget::close-button, QDockWidget::float-button {
    background: darkgray;
    padding: 0px;
    icon-size: 14px; /* maximum icon size */
}

QDockWidget::close-button:hover, QDockWidget::float-button:hover {
    background: gray;
}

QDockWidget::close-button:pressed, QDockWidget::float-button:pressed {
    padding: 1px -1px -1px 1px;
}

QDockWidget::close-button {
    subcontrol-position: top left;
    subcontrol-origin: margin;
    position: absolute;
    top: 0px; left: 0px; bottom: 0px;
    width: 14px;
}

QDockWidget::float-button {
    subcontrol-position: top left;
    subcontrol-origin: margin;
    position: absolute;
    top: 0px; left: 16px; bottom: 0px;
    width: 14px;
}

注意

要自定义QDockWidget的分隔符(调整大小手柄),请使用QMainWindow::separator。

自定义QFrame#

QFrame的样式使用The Box Model

QFrame, QLabel, QToolTip {
    border: 2px solid green;
    border-radius: 4px;
    padding: 2px;
    background-image: url(images/welcome.png);
}

自定义QGroupBox#

让我们来看一个例子,将QGroupBox的标题移动到中心。

QGroupBox {
    background-color: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1,
                                      stop: 0 #E0E0E0, stop: 1 #FFFFFF);
    border: 2px solid gray;
    border-radius: 5px;
    margin-top: 1ex; /* leave space at the top for the title */
}

QGroupBox::title {
    subcontrol-origin: margin;
    subcontrol-position: top center; /* position at the top center */
    padding: 0 3px;
    background-color: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1,
                                      stop: 0 #FF0ECE, stop: 1 #FFFFFF);
}

对于可复选的QGroupBox,请使用{#indicator-sub}{::indicator}子控件,并像QCheckBox(即)一样对其进行样式化

QGroupBox::indicator {
    width: 13px;
    height: 13px;
}

QGroupBox::indicator:unchecked {
    image: url(:/images/checkbox_unchecked.png);
}

/* proceed with styling just like QCheckBox */

自定义QHeaderView#

QHeaderView的自定义方式如下

QHeaderView::section {
    background-color: qlineargradient(x1:0, y1:0, x2:0, y2:1,
                                      stop:0 #616161, stop: 0.5 #505050,
                                      stop: 0.6 #434343, stop:1 #656565);
    color: white;
    padding-left: 4px;
    border: 1px solid #6c6c6c;
}

QHeaderView::section:checked
{
    background-color: red;
}

/* style the sort indicator */
QHeaderView::down-arrow {
    image: url(down_arrow.png);
}

QHeaderView::up-arrow {
    image: url(up_arrow.png);
}

自定义QLineEdit#

QLineEdit的框架使用The Box Model。要创建一个圆角文本框,我们可以设置

QLineEdit {
    border: 2px solid gray;
    border-radius: 10px;
    padding: 0 8px;
    background: yellow;
    selection-background-color: darkgray;
}

具有密码密码模式的文本的密码字符可以使用以下方法设置

QLineEdit[echoMode="2"] {
    lineedit-password-character: 9679;
}

可以按照以下方式修改只读QLineEdit的背景

QLineEdit:read-only {
    background: lightblue;
}

自定义QListView#

可以使用以下样式表自定义交替行的背景颜色

QListView {
    alternate-background-color: yellow;
}

要为鼠标悬停提供特殊背景,我们可以使用::item子控件。例如,

QListView {
    show-decoration-selected: 1; /* make the selection span the entire width of the view */
}

QListView::item:alternate {
    background: #EEEEEE;
}

QListView::item:selected {
    border: 1px solid #6a6ea9;
}

QListView::item:selected:!active {
    background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1,
                                stop: 0 #ABAFE5, stop: 1 #8588B2);
}

QListView::item:selected:active {
    background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1,
                                stop: 0 #6a6ea9, stop: 1 #888dd9);
}

QListView::item:hover {
    background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1,
                                stop: 0 #FAFBFE, stop: 1 #DCDEF1);
}

自定义QMainWindow#

可以按以下方式对QMainWindow的分隔符进行样式化

QMainWindow::separator {
    background: yellow;
    width: 10px; /* when vertical */
    height: 10px; /* when horizontal */
}

QMainWindow::separator:hover {
    background: red;
}

自定义 QMenu#

QMenu 的各项都是使用以下“item”子控件进行样式化

QMenu {
    background-color: #ABABAB; /* sets background of the menu */
    border: 1px solid black;
}

QMenu::item {
    /* sets background of menu item. set this to something non-transparent
        if you want menu color and menu item color to be different */
    background-color: transparent;
}

QMenu::item:selected { /* when user selects item using mouse or keyboard */
    background-color: #654321;
}

对于更高级的自定义,可以使用以下样式表

QMenu {
    background-color: white;
    margin: 2px; /* some spacing around the menu */
}

QMenu::item {
    padding: 2px 25px 2px 20px;
    border: 1px solid transparent; /* reserve space for selection border */
}

QMenu::item:selected {
    border-color: darkblue;
    background: rgba(100, 100, 100, 150);
}

QMenu::icon:checked { /* appearance of a 'checked' icon */
    background: gray;
    border: 1px inset gray;
    position: absolute;
    top: 1px;
    right: 1px;
    bottom: 1px;
    left: 1px;
}

QMenu::separator {
    height: 2px;
    background: lightblue;
    margin-left: 10px;
    margin-right: 5px;
}

QMenu::indicator {
    width: 13px;
    height: 13px;
}

/* non-exclusive indicator = check box style indicator (see QActionGroup::setExclusive) */
QMenu::indicator:non-exclusive:unchecked {
    image: url(:/images/checkbox_unchecked.png);
}

QMenu::indicator:non-exclusive:unchecked:selected {
    image: url(:/images/checkbox_unchecked_hover.png);
}

QMenu::indicator:non-exclusive:checked {
    image: url(:/images/checkbox_checked.png);
}

QMenu::indicator:non-exclusive:checked:selected {
    image: url(:/images/checkbox_checked_hover.png);
}

/* exclusive indicator = radio button style indicator (see QActionGroup::setExclusive) */
QMenu::indicator:exclusive:unchecked {
    image: url(:/images/radiobutton_unchecked.png);
}

QMenu::indicator:exclusive:unchecked:selected {
    image: url(:/images/radiobutton_unchecked_hover.png);
}

QMenu::indicator:exclusive:checked {
    image: url(:/images/radiobutton_checked.png);
}

QMenu::indicator:exclusive:checked:selected {
    image: url(:/images/radiobutton_checked_hover.png);
}

自定义 QMenuBar#

QMenuBar 的样式如下

QMenuBar {
    background-color: qlineargradient(x1:0, y1:0, x2:0, y2:1,
                                      stop:0 lightgray, stop:1 darkgray);
    spacing: 3px; /* spacing between menu bar items */
}

QMenuBar::item {
    padding: 1px 4px;
    background: transparent;
    border-radius: 4px;
}

QMenuBar::item:selected { /* when selected using mouse or keyboard */
    background: #a8a8a8;
}

QMenuBar::item:pressed {
    background: #888888;
}

自定义 QProgressBar#

QProgressBar 的边框、块状文本对齐可以通过使用样式表来自定义。然而,如果一个属性或子控件被自定义,所有其他属性或子控件都必须自定义。

../_images/progressBar-stylesheet.png

例如,我们将边框更改为灰色,块状更改为天蓝色。

QProgressBar {
    border: 2px solid grey;
    border-radius: 5px;
}

QProgressBar::chunk {
    background-color: #05B8CC;
    width: 20px;
}

这留出了文本对齐,我们通过将文本定位在进度条中心来自定义它。

QProgressBar {
    border: 2px solid grey;
    border-radius: 5px;
    text-align: center;
}

可以包括一个边距来获得更可见的块状。

../_images/progressBar2-stylesheet.png

在上面的屏幕截图中,我们使用了一个 0.5 像素的边距

QProgressBar::chunk {
    background-color: #CD96CD;
    width: 10px;
    margin: 0.5px;
}

自定义 QPushButton#

QPushButton 的样式如下

QPushButton {
    border: 2px solid #8f8f91;
    border-radius: 6px;
    background-color: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1,
                                      stop: 0 #f6f7fa, stop: 1 #dadbde);
    min-width: 80px;
}

QPushButton:pressed {
    background-color: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1,
                                      stop: 0 #dadbde, stop: 1 #f6f7fa);
}

QPushButton:flat {
    border: none; /* no border for a flat push button */
}

QPushButton:default {
    border-color: navy; /* make the default button prominent */
}

对于一个带有菜单的 QPushButton,使用 ::menu-indicator 子控件。

QPushButton:open { /* when the button has its menu open */
    background-color: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1,
                                      stop: 0 #dadbde, stop: 1 #f6f7fa);
}

QPushButton::menu-indicator {
    image: url(menu_indicator.png);
    subcontrol-origin: padding;
    subcontrol-position: bottom right;
}

QPushButton::menu-indicator:pressed, QPushButton::menu-indicator:open {
    position: relative;
    top: 2px; left: 2px; /* shift the arrow by 2 px */
}

可选的 QPushButton 拥有 :checked 伪状态。

自定义 QRadioButton#

可以使用以下方式更改 QRadioButton 的指示器

QRadioButton::indicator {
    width: 13px;
    height: 13px;
}

QRadioButton::indicator::unchecked {
    image: url(:/images/radiobutton_unchecked.png);
}

QRadioButton::indicator:unchecked:hover {
    image: url(:/images/radiobutton_unchecked_hover.png);
}

QRadioButton::indicator:unchecked:pressed {
    image: url(:/images/radiobutton_unchecked_pressed.png);
}

QRadioButton::indicator::checked {
    image: url(:/images/radiobutton_checked.png);
}

QRadioButton::indicator:checked:hover {
    image: url(:/images/radiobutton_checked_hover.png);
}

QRadioButton::indicator:checked:pressed {
    image: url(:/images/radiobutton_checked_pressed.png);
}

自定义 QScrollBar#

可以使用子控件,如 handleadd-linesub-line 等,对 QScrollBar 进行样式化。注意,如果一个属性或子控件被自定义,所有其他属性或子控件都必须自定义。

../_images/stylesheet-scrollbar1.png

上方的滚动条已被用碧绿色装饰,并带有实线灰色边框。

QScrollBar:horizontal {
    border: 2px solid grey;
    background: #32CC99;
    height: 15px;
    margin: 0px 20px 0 20px;
}
QScrollBar::handle:horizontal {
    background: white;
    min-width: 20px;
}
QScrollBar::add-line:horizontal {
    border: 2px solid grey;
    background: #32CC99;
    width: 20px;
    subcontrol-position: right;
    subcontrol-origin: margin;
}

QScrollBar::sub-line:horizontal {
    border: 2px solid grey;
    background: #32CC99;
    width: 20px;
    subcontrol-position: left;
    subcontrol-origin: margin;
}

左箭头右箭头带有实线灰色边框和白色背景。作为替代方案,您也可以嵌入箭头的图像。

QScrollBar::left-arrow:horizontal, QScrollBar::right-arrow:horizontal {
    border: 2px solid grey;
    width: 3px;
    height: 3px;
    background: white;
}

QScrollBar::add-page:horizontal, QScrollBar::sub-page:horizontal {
    background: none;
}

如果想让滚动条上的滚动按钮(而非边缘)像在macOS上一样并排放置,可以使用以下样式表

QScrollBar:horizontal {
    border: 2px solid green;
    background: cyan;
    height: 15px;
    margin: 0px 40px 0 0px;
}

QScrollBar::handle:horizontal {
    background: gray;
    min-width: 20px;
}

QScrollBar::add-line:horizontal {
    background: blue;
    width: 16px;
    subcontrol-position: right;
    subcontrol-origin: margin;
    border: 2px solid black;
}

QScrollBar::sub-line:horizontal {
    background: magenta;
    width: 16px;
    subcontrol-position: top right;
    subcontrol-origin: margin;
    border: 2px solid black;
    position: absolute;
    right: 20px;
}

QScrollBar::left-arrow:horizontal, QScrollBar::right-arrow:horizontal {
    width: 3px;
    height: 3px;
    background: pink;
}

QScrollBar::add-page:horizontal, QScrollBar::sub-page:horizontal {
    background: none;
}

使用上述样式表的滚动条看起来如下

../_images/stylesheet-scrollbar2.png

要自定义垂直滚动条,请使用类似以下样式的样式表

QScrollBar:vertical {
    border: 2px solid grey;
    background: #32CC99;
    width: 15px;
    margin: 22px 0 22px 0;
}
QScrollBar::handle:vertical {
    background: white;
    min-height: 20px;
}
QScrollBar::add-line:vertical {
    border: 2px solid grey;
    background: #32CC99;
    height: 20px;
    subcontrol-position: bottom;
    subcontrol-origin: margin;
}

QScrollBar::sub-line:vertical {
    border: 2px solid grey;
    background: #32CC99;
    height: 20px;
    subcontrol-position: top;
    subcontrol-origin: margin;
}
QScrollBar::up-arrow:vertical, QScrollBar::down-arrow:vertical {
    border: 2px solid grey;
    width: 3px;
    height: 3px;
    background: white;
}

QScrollBar::add-page:vertical, QScrollBar::sub-page:vertical {
    background: none;
}

定制QSizeGrip#

QSizeGrip一般只需设置一个图像来进行定制。

QSizeGrip {
    image: url(:/images/sizegrip.png);
    width: 16px;
    height: 16px;
}

定制QSlider#

您可以将水平滑块样式设置为如下

QSlider::groove:horizontal {
    border: 1px solid #999999;
    height: 8px; /* the groove expands to the size of the slider by default. by giving it a height, it has a fixed size */
    background: qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:0 #B1B1B1, stop:1 #c4c4c4);
    margin: 2px 0;
}

QSlider::handle:horizontal {
    background: qlineargradient(x1:0, y1:0, x2:1, y2:1, stop:0 #b4b4b4, stop:1 #8f8f8f);
    border: 1px solid #5c5c5c;
    width: 18px;
    margin: -2px 0; /* handle is placed by default on the contents rect of the groove. Expand outside the groove */
    border-radius: 3px;
}

如果您想更改变量控制前后部分的滑块的色彩,可以使用添加页面和子页面的子控件。例如,对于垂直滑块

QSlider::groove:vertical {
    background: red;
    position: absolute; /* absolutely position 4px from the left and right of the widget. setting margins on the widget should work too... */
    left: 4px; right: 4px;
}

QSlider::handle:vertical {
    height: 10px;
    background: green;
    margin: 0 -4px; /* expand outside the groove */
}

QSlider::add-page:vertical {
    background: white;
}

QSlider::sub-page:vertical {
    background: pink;
}

定制QSpinBox#

QSpinBox可以完全按以下样式(样式表中包含了行内注释)来定制。

QSpinBox {
    padding-right: 15px; /* make room for the arrows */
    border-image: url(:/images/frame.png) 4;
    border-width: 3;
}

QSpinBox::up-button {
    subcontrol-origin: border;
    subcontrol-position: top right; /* position at the top right corner */

    width: 16px; /* 16 + 2*1px border-width = 15px padding + 3px parent border */
    border-image: url(:/images/spinup.png) 1;
    border-width: 1px;
}

QSpinBox::up-button:hover {
    border-image: url(:/images/spinup_hover.png) 1;
}

QSpinBox::up-button:pressed {
    border-image: url(:/images/spinup_pressed.png) 1;
}

QSpinBox::up-arrow {
    image: url(:/images/up_arrow.png);
    width: 7px;
    height: 7px;
}

QSpinBox::up-arrow:disabled, QSpinBox::up-arrow:off { /* off state when value is max */
   image: url(:/images/up_arrow_disabled.png);
}

QSpinBox::down-button {
    subcontrol-origin: border;
    subcontrol-position: bottom right; /* position at bottom right corner */

    width: 16px;
    border-image: url(:/images/spindown.png) 1;
    border-width: 1px;
    border-top-width: 0;
}

QSpinBox::down-button:hover {
    border-image: url(:/images/spindown_hover.png) 1;
}

QSpinBox::down-button:pressed {
    border-image: url(:/images/spindown_pressed.png) 1;
}

QSpinBox::down-arrow {
    image: url(:/images/down_arrow.png);
    width: 7px;
    height: 7px;
}

QSpinBox::down-arrow:disabled,
QSpinBox::down-arrow:off { /* off state when value in min */
   image: url(:/images/down_arrow_disabled.png);
}

定制QSplitter#

的一个QSplitterQFrame派生出来,因此可以像QFrame一样进行定制。握把或手柄可以通过使用::handle子控件进行定制。

QSplitter::handle {
    image: url(images/splitter.png);
}

QSplitter::handle:horizontal {
    width: 2px;
}

QSplitter::handle:vertical {
    height: 2px;
}

QSplitter::handle:pressed {
    url(images/splitter_pressed.png);
}

定制QStatusBar#

我们可以如下提供状态栏的背景以及状态栏内条目的边框

QStatusBar {
    background: brown;
}

QStatusBar::item {
    border: 1px solid red;
    border-radius: 3px;
}

请注意,已经添加到QStatusBar中的小部件可以使用后代声明进行样式定制(即)

QStatusBar QLabel {
    border: 3px solid white;
}

定制QTabWidget和QTabBar#

../_images/tabWidget-stylesheet1.png

对于上述截图,我们需要以下样式表

QTabWidget::pane { /* The tab widget frame */
    border-top: 2px solid #C2C7CB;
}

QTabWidget::tab-bar {
    left: 5px; /* move to the right by 5px */
}

/* Style the tab using the tab sub-control. Note that
    it reads QTabBar _not_ QTabWidget */
QTabBar::tab {
    background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1,
                                stop: 0 #E1E1E1, stop: 0.4 #DDDDDD,
                                stop: 0.5 #D8D8D8, stop: 1.0 #D3D3D3);
    border: 2px solid #C4C4C3;
    border-bottom-color: #C2C7CB; /* same as the pane color */
    border-top-left-radius: 4px;
    border-top-right-radius: 4px;
    min-width: 8ex;
    padding: 2px;
}

QTabBar::tab:selected, QTabBar::tab:hover {
    background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1,
                                stop: 0 #fafafa, stop: 0.4 #f4f4f4,
                                stop: 0.5 #e7e7e7, stop: 1.0 #fafafa);
}

QTabBar::tab:selected {
    border-color: #9B9B9B;
    border-bottom-color: #C2C7CB; /* same as pane color */
}

QTabBar::tab:!selected {
    margin-top: 2px; /* make non-selected tabs look smaller */
}

我们通常需要标签重叠以呈现如下效果

../_images/tabWidget-stylesheet2.png

对于上述外观的标签页,我们会使用负边距。负值会使得元素比默认情况下更靠近其相邻元素。结果样式表看起来如下

QTabWidget::pane { /* The tab widget frame */
    border-top: 2px solid #C2C7CB;
}

QTabWidget::tab-bar {
    left: 5px; /* move to the right by 5px */
}

/* Style the tab using the tab sub-control. Note that
    it reads QTabBar _not_ QTabWidget */
QTabBar::tab {
    background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1,
                                stop: 0 #E1E1E1, stop: 0.4 #DDDDDD,
                                stop: 0.5 #D8D8D8, stop: 1.0 #D3D3D3);
    border: 2px solid #C4C4C3;
    border-bottom-color: #C2C7CB; /* same as the pane color */
    border-top-left-radius: 4px;
    border-top-right-radius: 4px;
    min-width: 8ex;
    padding: 2px;
}

QTabBar::tab:selected, QTabBar::tab:hover {
    background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1,
                                stop: 0 #fafafa, stop: 0.4 #f4f4f4,
                                stop: 0.5 #e7e7e7, stop: 1.0 #fafafa);
}

QTabBar::tab:selected {
    border-color: #9B9B9B;
    border-bottom-color: #C2C7CB; /* same as pane color */
}

QTabBar::tab:!selected {
    margin-top: 2px; /* make non-selected tabs look smaller */
}

/* make use of negative margins for overlapping tabs */
QTabBar::tab:selected {
    /* expand/overlap to the left and right by 4px */
    margin-left: -4px;
    margin-right: -4px;
}

QTabBar::tab:first:selected {
    margin-left: 0; /* the first selected tab has nothing to overlap with on the left */
}

QTabBar::tab:last:selected {
    margin-right: 0; /* the last selected tab has nothing to overlap with on the right */
}

QTabBar::tab:only-one {
    margin: 0; /* if there is only one tab, we don't want overlapping margins */
}

要将标签栏移至中心(如下所示),我们需要以下样式表

../_images/tabWidget-stylesheet3.png
QTabWidget::pane { /* The tab widget frame */
    border-top: 2px solid #C2C7CB;
    position: absolute;
    top: -0.5em;
}

QTabWidget::tab-bar {
    alignment: center;
}

/* Style the tab using the tab sub-control. Note that
    it reads QTabBar _not_ QTabWidget */
QTabBar::tab {
    background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1,
                                stop: 0 #E1E1E1, stop: 0.4 #DDDDDD,
                                stop: 0.5 #D8D8D8, stop: 1.0 #D3D3D3);
    border: 2px solid #C4C4C3;
    border-bottom-color: #C2C7CB; /* same as the pane color */
    border-top-left-radius: 4px;
    border-top-right-radius: 4px;
    min-width: 8ex;
    padding: 2px;
}

QTabBar::tab:selected, QTabBar::tab:hover {
    background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1,
                                stop: 0 #fafafa, stop: 0.4 #f4f4f4,
                                stop: 0.5 #e7e7e7, stop: 1.0 #fafafa);
}

QTabBar::tab:selected {
    border-color: #9B9B9B;
    border-bottom-color: #C2C7CB; /* same as pane color */
}

撕裂指示器和滚动按钮可以进一步定制如下

QTabBar::tear {
    image: url(tear_indicator.png);
}

QTabBar::scroller { /* the width of the scroll buttons */
    width: 20px;
}

QTabBar QToolButton { /* the scroll buttons are tool buttons */
    border-image: url(scrollbutton.png) 2;
    border-width: 2px;
}

QTabBar QToolButton::right-arrow { /* the arrow mark in the tool buttons */
    image: url(rightarrow.png);
}

QTabBar QToolButton::left-arrow {
    image: url(leftarrow.png);
}

自Qt 4.6以来,关闭按钮可以定制如下

QTabBar::close-button {
    image: url(close.png)
    subcontrol-position: left;
}
QTabBar::close-button:hover {
    image: url(close-hover.png)
}

定制QTableView#

假设我们想在QTableView中选择的项目以果冻粉色渐变至白色作为其背景。

../_images/tableWidget-stylesheet.png

使用 选择背景颜色 属性可以实现此功能,所需语法如下

QTableView {
    selection-background-color: qlineargradient(x1: 0, y1: 0, x2: 0.5, y2: 0.5,
                                stop: 0 #FF92BB, stop: 1 white);
}

可以通过以下样式表自定义角落小部件

QTableView QTableCornerButton::section {
    background: red;
    border: 2px outset red;
}

QTableView 的复选框指示器也可以自定义。以下是复选框未经选中状态的指示器 背景颜色 自定义的示例代码片段

QTableView::indicator:unchecked {
    background-color: #d7d6d5
}

自定义 QToolBar#

自定义 QToolBar# 的背景和句柄如下

QToolBar {
    background: red;
    spacing: 3px; /* spacing between items in the tool bar */
}

QToolBar::handle {
    image: url(handle.png);
}

自定义 QToolBox#

使用

QToolBox::tab {
    background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1,
                                stop: 0 #E1E1E1, stop: 0.4 #DDDDDD,
                                stop: 0.5 #D8D8D8, stop: 1.0 #D3D3D3);
    border-radius: 5px;
    color: darkgray;
}

QToolBox::tab:selected { /* italicize selected tabs */
    font: italic;
    color: white;
}

自定义 QToolButton#

QToolButton 有三种类型。

QToolButton { /* all types of tool button */
    border: 2px solid #8f8f91;
    border-radius: 6px;
    background-color: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1,
                                      stop: 0 #f6f7fa, stop: 1 #dadbde);
}

QToolButton[popupMode="1"] { /* only for MenuButtonPopup */
    padding-right: 20px; /* make way for the popup button */
}

QToolButton:pressed {
    background-color: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1,
                                      stop: 0 #dadbde, stop: 1 #f6f7fa);
}

/* the subcontrols below are used only in the MenuButtonPopup mode */
QToolButton::menu-button {
    border: 2px solid gray;
    border-top-right-radius: 6px;
    border-bottom-right-radius: 6px;
    /* 16px width + 4px for border = 20px allocated above */
    width: 16px;
}

QToolButton::menu-arrow {
    image: url(downarrow.png);
}

QToolButton::menu-arrow:open {
    top: 1px; left: 1px; /* shift it a bit */
}

自定义 QToolTip#

QToolTip 的自定义方法与 QLabel 完全相同。此外,对于支持的平台,可以通过设置不透明度属性来调整不透明度。

例如,

QToolTip {
    border: 2px solid darkkhaki;
    padding: 5px;
    border-radius: 3px;
    opacity: 200;
}

自定义 QTreeView#

可以使用以下样式表自定义交替行的背景颜色

QTreeView {
    alternate-background-color: yellow;
}

要为鼠标悬停提供特殊背景,我们可以使用::item子控件。例如,

QTreeView {
    show-decoration-selected: 1;
}

QTreeView::item {
     border: 1px solid #d9d9d9;
    border-top-color: transparent;
    border-bottom-color: transparent;
}

QTreeView::item:hover {
    background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, stop: 0 #e7effd, stop: 1 #cbdaf1);
    border: 1px solid #bfcde4;
}

QTreeView::item:selected {
    border: 1px solid #567dbc;
}

QTreeView::item:selected:active{
    background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, stop: 0 #6ea1f1, stop: 1 #567dbc);
}

QTreeView::item:selected:!active {
    background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, stop: 0 #6b9be8, stop: 1 #577fbf);
}

QTreeView 的分支使用 QTreeView 的 ::branch 子控件进行样式设置。以下样式表使用颜色代码为绘制分支的各种状态着色。

QTreeView::branch {
        background: palette(base);
}

QTreeView::branch:has-siblings:!adjoins-item {
        background: cyan;
}

QTreeView::branch:has-siblings:adjoins-item {
        background: red;
}

QTreeView::branch:!has-children:!has-siblings:adjoins-item {
        background: blue;
}

QTreeView::branch:closed:has-children:has-siblings {
        background: pink;
}

QTreeView::branch:has-children:!has-siblings:closed {
        background: gray;
}

QTreeView::branch:open:has-children:has-siblings {
        background: magenta;
}

QTreeView::branch:open:has-children:!has-siblings {
        background: green;
}

虽然色彩丰富,但使用以下图像制作一个更有用的示例会更有效

stylesheet-vline1

stylesheet-branch-more2

stylesheet-branch-end3

stylesheet-branch-closed4

stylesheet-branch-open5

vline.png

branch-more.png

branch-end.png

branch-closed.png

branch-open.png

QTreeView::branch:has-siblings:!adjoins-item {
    border-image: url(vline.png) 0;
}

QTreeView::branch:has-siblings:adjoins-item {
    border-image: url(branch-more.png) 0;
}

QTreeView::branch:!has-children:!has-siblings:adjoins-item {
    border-image: url(branch-end.png) 0;
}

QTreeView::branch:has-children:!has-siblings:closed,
QTreeView::branch:closed:has-children:has-siblings {
        border-image: none;
        image: url(branch-closed.png);
}

QTreeView::branch:open:has-children:!has-siblings,
QTreeView::branch:open:has-children:has-siblings  {
        border-image: none;
        image: url(branch-open.png);
}

生成的树视图看起来像这样

../_images/stylesheet-treeview.png

常见错误#

本节列举了使用样式表时的一些常见错误。

QPushButton 和图像#

在设置 QPushButton 的样式时,通常希望使用图像作为按钮图形。通常会尝试使用 background-image 属性,但这种方法有一系列缺点:例如,背景通常会隐藏在按钮装饰后面,因为它不被认为是背景。此外,如果按钮被调整大小,整个背景将被拉伸或平铺,这并不总是看起来很好。

最好使用 border-image 属性,因为它会始终显示图像,无论背景如何(如果它包含透明度值,可以将其与背景组合),并且它有特殊的设置来处理按钮调整大小。

考虑以下片段

QPushButton {
    color: grey
    border-image: url(/home/kamlie/code/button.png) 3 10 3 10
    border-top: 3px transparent
    border-bottom: 3px transparent
    border-right: 10px transparent
    border-left: 10px transparent

这将产生一个看起来像这样的按钮

../_images/stylesheet-border-image-normal.png

url 后的数字分别表示顶部、右侧、底部和左侧的像素数。这些数字对应于边框,并且在大小变化时不应拉伸。每次调整按钮大小时,图像的中间部分将在两个方向拉伸,而样式表中指定的像素则不会。这使得按钮的边框看起来更加自然,如下所示

stylesheet-border-image-stretched6

带有边框

stylesheet-border-image-wrong7

没有边框

另请参阅

QStyle