paintEvent():針對單一組件類別微調繪製,工作量大但精準可控。QStyle/QProxyStyle:統一整個應用的風格,適合主題級定製。⚠️ QStyle 極其複雜 (百餘虛函數),非必要勿深入。Qt 4.6+ 提供 QProxyStyle 代理模式,僅覆寫關心的函數,其餘委託給系統風格,大幅降低複雜度。
paintEvent() — 以 QPushButton 為例自繪按鈕,點擊時呈現凹陷效果。
QPushButton。paintEvent(QPaintEvent*)。QStyleOptionButton 傳遞繪製參數。style()->drawControl(...) 讓系統風格按我們參數繪製。void MyPushButton::paintEvent(QPaintEvent*)
{
QStyleOptionButton option;
option.initFrom(this); // 以 widget 狀態初始化
option.state |= isDown() ? QStyle::State_Sunken : QStyle::State_Raised; // 按下/彈起
if (isDefault()) option.features |= QStyleOptionButton::DefaultButton; // 預設按鈕特徵
option.text = text();
option.icon = icon();
QPainter painter(this);
style()->drawControl(QStyle::CE_PushButton, &option, &painter, this);
}
QStyleOptionButton:承載繪製所需所有資料 (幾何、狀態、文字、圖示、特徵)。option.state 為 QFlags (位圖),**必須用 |= 而非 =**,否則會清除其他狀態位 (如焦點、啟用、滑鼠懸停等)。drawControl(ControlElement, QStyleOption*, QPainter*, QWidget*):通用組件繪製入口。CE_PushButton 代表按鈕整體。QProxyStyle — 全域風格定製class MyProxyStyle : public QProxyStyle
{
public:
void drawControl(ControlElement element, const QStyleOption* option,
QPainter* painter, const QWidget* widget) const override
{
if (element == QStyle::CE_PushButtonLabel) {
painter->drawText(option->rect, "fixed"); // 忽略原本文字
} else {
QProxyStyle::drawControl(element, option, painter, widget); // 委託系統
}
}
};
int main(int argc, char** argv)
{
QApplication app(argc, argv);
app.setStyle(new MyProxyStyle); // 應用啟動前設定
MainWindow w;
w.show();
return app.exec();
}
| 目標 | 建議覆寫函數 | 說明 |
|---|---|---|
| 修改特定組件外觀 | drawControl() | 判斷 element (CE_PushButton, CE_CheckBox...) |
| 修改基本元素 (焦點框、核取方塊勾號...) | drawPrimitive() | PrimitiveElement (PE_FrameFocusRect, PE_IndicatorCheckBox...) |
| 調整佈局間距、尺寸 | pixelMetric() | 回傳像素度量 (PM_ButtonMargin, PM_DefaultFrameWidth...) |
| 提供自定義圖示 | standardIcon() | 標準圖示 (SP_FileIcon, SP_MessageBoxWarning...) |
| 字體/調色板微調 | standardPalette(), font() | 較建議用 QApplication::setPalette/Font |
QProxyStyle。qwindowsstyle.cpp, qmacstyle.mm 等) 是最佳範例與文檔。自定義 QStyle 是 Qt 視覺定製的核武器,門檻高但威力大。掌握 QStyleOption 資料流向與 QProxyStyle 代理模式,即可在保留跨平台優勢的前提下,精準注入品牌風格或平台適配細節。