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 }");

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

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 }

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

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

QLineEdit *nameEdit = new QLineEdit(this);
nameEdit->setProperty("mandatoryField", true);

QLineEdit *emailEdit = new QLineEdit(this);
emailEdit->setProperty("mandatoryField", true);

QSpinBox *ageSpinBox = new QSpinBox(this);
ageSpinBox->setProperty("mandatoryField", true);

使用盒模型自定义QPushButton

这次,我们将展示如何创建一个红色的QPushButton。显然,这个QPushButton可能连接到一些极具破坏性的代码。

首先,我们可能想使用这个样式表

QPushButton#evilButton { background-color: red }

然而,结果是平淡无奇、没有边框的按钮

A flat red button

发生的事情是这样的

  • 我们提出了一个无法仅使用本地样式满足的要求(例如,Windows Vista主题引擎不允许我们指定按钮的背景颜色)。
  • 因此,按钮使用样式表进行渲染。
  • 我们没有指定border-widthborder-style的任何值,因此默认情况下我们获得了宽度为0像素的边框,风格为none

让我们通过指定边框来改善这种情况

QPushButton#evilButton {
    background-color: red;
    border-style: outset;
    border-width: 2px;
    border-color: beige;
}

A red button with a beige border

事物看起来已经好多了。但按钮看起来有些拥挤。让我们一起使用填充属性来指定边框和文本之间的间距。此外,我们还将强制一个最小宽度,使角落圆润,并指定较大的字体以确保按钮看起来更好。

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;
}

A red button with a round beige border and big, bold text

唯一剩下的问题是按钮在按下时没有反应。我们可以通过指定不同的背景颜色和不同的边框样式来解决这个问题。

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(使用QPushButton::setMenu())有一个菜单指标。让我们为红色的QPushButton自定义菜单指标。

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

默认情况下,菜单指标位于填充矩形的右下角。我们可以通过指定子控件位置和子控件源来不同的定位指标。我们还可以使用顶部和左侧来移动指示器几个像素。例如

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

这样可以将其位置定位为QPushButton的填充矩形的右上角(有关更多信息,请参阅子控件源)。

复杂选择器示例

因为红色似乎是我们最喜欢的颜色,所以让我们通过设置以下应用程序范围的样式来使QLineEdit中的文本变红

QLineEdit { color: red }

然而,我们希望通过使其看起来灰色来提供一种视觉指示,以表明QLineEdit是只读的

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

在某个时候,我们的设计团队提出了要将注册表单中所有(以对象名称 registrationDialog为名的)QLineEdit设为棕色的要求

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(项目视图、QTextEdit和QTextBrowser)的背景,使用背景属性。例如,要设置一个随着滚动条滚动背景图片

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使用盒模型进行样式设置。

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的框架进行样式设置。为了创建圆角行编辑,我们可以设置:

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

对于具有QLineEdit::Password回显模式的行编辑,可以通过以下方式设置密码字符:

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

可以使用如下方式使用“item”子控件样式化QMenu的各个项

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边框文本对齐。但是,如果自定义了某个属性或子控件,则必须同时自定义其他属性或子控件。

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

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;
}

可以在其中包含外边距以获得更明显的块。

在上面的屏幕截图中,我们使用了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

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

上面的滚动条已使用翠绿色填充,并有实线灰色边框。

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;
}

使用上述样式表的滚动条看起来像这样

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

 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;
}

如果您想更改滑块把手前后部分的颜色,可以使用 add-page 和 sub-page 子控件。例如,对于垂直滑块

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

QSplitter 继承自 QFrame,因此可以像 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

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

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 */
}

通常我们需要的选项卡需要重叠,如下所示

对于看起来像上面的选项卡控件,我们利用了 负边距。负值会将元素画得比默认情况下更靠近它的邻居。结果是样式表看起来如下

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 */
}

要将选项卡栏移动到中间(如下所示),我们需要以下样式表

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 中的选定项具有薄荷粉色渐变到白色的背景。

这可以通过 selection-background-color 属性实现,所需的语法如下

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

使用 'tab' 子控件自定义 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

QToolTipQLabel 的样式完全相同。此外,对于支持的平台,可以设置不透明度属性以调整不透明度。

例如:

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 的分支使用 ::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;
}

虽然它很丰富多彩,但使用以下图像可以创建更实用的示例

vline.pngbranch-more.pngbranch-end.pngbranch-closed.pngbranch-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);
}

结果树视图看起来如下

常见错误

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

QPushButton 和图像

在样式化 QPushButton 时,通常希望使用图像作为按钮图形。人们常常尝试使用 background-image 属性,但这有几个缺点:例如,由于背景不被认为是背景,它常常会出现在按钮装饰的后面,变得不可见。此外,如果按钮被调整大小,整个背景将会被拉伸或平铺,这通常看起来并不理想。

最好使用 border-image 属性,因为它会始终显示图像,无论背景如何(如果有alpha值,还可以与背景结合使用),并且它有专门的处理按钮尺寸调整的设置。

考虑以下代码片段:

        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;
        }

这将产生以下外观的按钮

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

带有边框
不带边框

另请参阅 支持的HTML子集QStyle

© 2024 The Qt Company Ltd. 包含在此处的文档贡献有各自所有者的版权。提供的文档按照自由软件基金会发布的GNU自由文档许可协议的条款进行许可,版本为1.3。Qt及其相关标志是The Qt Company Ltd.在芬兰和其他国家的商标。所有其他商标均为其各自所有者的财产。