Qt Style Sheet (QSS) 語法、選擇器、屬性名幾乎**完全對標 CSS 2.1**,差異在於:
QStyle 佈局 (contentsRect, padding, border, margin)。:enabled, :pressed, :checked, :focus 等)。pt, em, ex。⚠️ **慎用 QSS 破壞原生感**:過度自定義顏色/邊框會讓應用在各平台顯得「異類」。優先使用 palette(role) 參考系統調色板。
| 層級 | 範圍 | 代碼範例 |
|---|---|---|
| 應用程式全域 | 所有組件 | qApp->setStyleSheet("QToolTip { color: #fff; background: #333; }"); |
| 單一 Widget 及其子樹 | 局部 | widget->setStyleSheet("background: palette(window);"); |
| 單一 Widget 自身 (不繼承) | 精準控制 | widget->setStyleSheet("QPushButton { ... }"); // 僅影響該按鈕 |
// 錯誤:硬編碼紅色
label->setStyleSheet("color: red;");
// 正確:引用系統 Highlight 色
label->setStyleSheet("color: palette(highlight);");
// 動態色彩:從 QColor 轉名稱
QColor accent(128, 200, 128);
label->setStyleSheet(QString("color: %1;").arg(accent.name()));
palette(role) 可用角色:window, windowText, base, alternateBase, toolTipBase, toolTipText, text, button, buttonText, brightText, highlight, highlightedText, link, linkVisited 等。
QPushButton {
border: 2px solid palette(mid);
border-radius: 4px;
padding: 6px 12px;
background: palette(button);
}
QPushButton:pressed {
background: palette(mid);
}
QPushButton:disabled {
color: palette(mid);
}
準備 4 張圖 (已加入資源系統 :/img/...):
btn_left.png (正常左按鈕)btn_left_pressed.png (按下左按鈕)btn_right.png (正常右按鈕)btn_right_pressed.png (按下右按鈕)
QToolButton {
border-image: url(:/img/btn_left.png);
}
QToolButton:pressed {
border-image: url(:/img/btn_left_pressed.png);
}
/* 右按鈕需用物件名稱或屬性選擇器區分 */
QToolButton#forwardBtn {
border-image: url(:/img/btn_right.png);
}
QToolButton#forwardBtn:pressed {
border-image: url(:/img/btn_right_pressed.png);
}
QWidget segmentedButton;
QHBoxLayout* lay = new QHBoxLayout(&segmentedButton);
lay->setSpacing(0); lay->setMargin(0);
QToolButton* backBtn = new QToolButton(&segmentedButton);
QToolButton* fwdBtn = new QToolButton(&segmentedButton);
fwdBtn->setObjectName("forwardBtn"); // 對應 QSS 選擇器
backBtn->setFixedSize(28, 23);
fwdBtn->setFixedSize(28, 23);
lay->addWidget(backBtn);
lay->addWidget(fwdBtn);
// 外層容器消除視窗最小尺寸限制
QWidget win;
QHBoxLayout* winLay = new QHBoxLayout(&win);
winLay->setSpacing(0); winLay->setMargin(0);
winLay->setAlignment(Qt::AlignLeft);
winLay->addWidget(&segmentedButton);
win.show();
關鍵技巧:Windows 視窗有最小尺寸,直接 segmentedButton.show() 會導致按鈕分離。嵌套一層 QWidget 並設定 setMargin(0)/setSpacing(0) 可繞過限制。
| 選擇器 | 範例 | 說明 |
|---|---|---|
| 類別選擇器 | QPushButton | 所有按鈕 |
| ID 選擇器 | QPushButton#okBtn | objectName="okBtn" 的按鈕 |
| 屬性選擇器 | QPushButton[flat="true"] | flat 屬性為 true 的按鈕 |
| 後代選擇器 | QGroupBox QPushButton | 群組框內的按鈕 |
| 子代選擇器 | QAbstractScrollArea > QScrollBar | 直接子組件 |
| 偽狀態 | :hover, :pressed, :checked, :disabled, :focus, :enabled, :selected, :open (選單/下拉) | 互動狀態 |
| 場景 | 推薦方案 |
|---|---|
| 顏色、字體、間距、邊框、背景圖調整 | QSS (聲明式、熱重載、設計師友善) |
| 自定義組件佈局邏輯、複雜繪製行為、像素級控制 | QProxyStyle / paintEvent (命令式、完整控制) |
| 跨平台原生感微調 | QSS + palette() 為主,必要時 QProxyStyle 修正平台差異 |
QSS 是 Qt 視覺定製的「瑞士軍刀」:語法熟悉、效果即時、維護成本低。核心原則——**善用 palette() 而非硬編碼色彩**,讓應用在 Windows 深色模式、macOS Aqua、GNOME Adwaita、KDE Breeze 下都能自然融入。將複雜繪製邏輯留給 QStyle,QSS 專注於「皮膚層」的優雅變裝。