Qt 原始碼剖析 之 控制元件繪製
阿新 • • 發佈:2018-12-29
Qt 原始碼剖析 之 控制元件繪製
這裡使用QPushButton為例,講解一下具體QPushButton是怎麼繪製的
首先看一段程式碼,這段程式碼是QPushButton中的繪製事件函式,可以看出來是使用QStylePainter來繪製,
QStylePainter
包裝了所有高階控制元件的繪製, QStyleOptionButton
是按鈕的樣式引數的分裝類,所有有關按鈕的繪製樣式在QStyleOptionButton
都可找到。
initStyleOption
初始化引數
void QPushButton::paintEvent(QPaintEvent *) { QStylePainter p(this); QStyleOptionButton option; initStyleOption(&option); p.drawControl(QStyle::CE_PushButton, option); } void QPushButton::initStyleOption(QStyleOptionButton *option) const { if (!option) return; Q_D(const QPushButton); option->initFrom(this); option->features = QStyleOptionButton::None; if (d->flat) option->features |= QStyleOptionButton::Flat; #ifndef QT_NO_MENU if (d->menu) option->features |= QStyleOptionButton::HasMenu; #endif if (autoDefault()) option->features |= QStyleOptionButton::AutoDefaultButton; if (d->defaultButton) option->features |= QStyleOptionButton::DefaultButton; if (d->down || d->menuOpen) option->state |= QStyle::State_Sunken; if (d->checked) option->state |= QStyle::State_On; if (!d->flat && !d->down) option->state |= QStyle::State_Raised; option->text = d->text; option->icon = d->icon; option->iconSize = iconSize(); }
下面看一下QStylePainter 是怎麼繪製的
void QStylePainter::drawControl(QStyle::ControlElement ce, const QStyleOption &opt)
{
wstyle->drawControl(ce, &opt, this, widget);
}
wstyle 是QStyle的一個子類,Qt預設使用QCommonStyle,想修改Qt的樣式可以繼承QCommonStyle,
重寫裡面的一些虛擬函式就可以
看一下具體QCommonStyle是怎麼繪製控制元件的
void QCommonStyle::drawControl(ControlElement element, const QStyleOption *opt, QPainter *p, const QWidget *widget) const { Q_D(const QCommonStyle); switch (element) { case CE_PushButton: if (const QStyleOptionButton *btn = qstyleoption_cast<const QStyleOptionButton *>(opt)) { proxy()->drawControl(CE_PushButtonBevel, btn, p, widget); QStyleOptionButton subopt = *btn; subopt.rect = subElementRect(SE_PushButtonContents, btn, widget); proxy()->drawControl(CE_PushButtonLabel, &subopt, p, widget); if (btn->state & State_HasFocus) { QStyleOptionFocusRect fropt; fropt.QStyleOption::operator=(*btn); fropt.rect = subElementRect(SE_PushButtonFocusRect, btn, widget); proxy()->drawPrimitive(PE_FrameFocusRect, &fropt, p, widget); } } break; case CE_PushButtonBevel:
這裡給一個例子,修改Qt的預設空間繪製方式的一個例子
#include "textedit.h" #include <QApplication> #include <QProxyStyle> class MyProxyStyle : public QProxyStyle { public: int styleHint(StyleHint hint, const QStyleOption *option = 0, const QWidget *widget = 0, QStyleHintReturn *returnData = 0) const { if (hint == QStyle::SH_UnderlineShortcut) return 0; return QProxyStyle::styleHint(hint, option, widget, returnData); } }; int main(int argc, char **argv) { Q_INIT_RESOURCE(textedit); QApplication a(argc, argv); a.setStyle(new MyProxyStyle); TextEdit mw; mw.resize(700, 800); mw.show(); //... }