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();
//...
}