Qt 源码剖析 之 控件绘制

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(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 
  #include 

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

你可能感兴趣的:(C++,Qt)