Qt自绘滚动条

核心就是自定义一个派生自QWindowStyple类,重载drawScrollBarControls方法

最后在自己的QApplication中应用这个style

自定义style中绘制滚动条的过程

类继承关系:MetalStyle: QWindowsStyle:QStyle

void MetalStyle::drawScrollBarControls( QPainter* p, const QScrollBar* sb, int sliderStart,

uint controls, uint activeControl )

{

   // 先用父类的方法绘制除了AddLine|SubLine|Slider之外的控件

   // 对于垂直滚动条,就是:向下箭头|向上箭头|滑块

   QWindowsStyle::drawScrollBarControls(p,sb,sliderStart,controls&~(AddLine|SubLine|Slider),         activeControl & ~(AddLine|SubLine|Slider) );

bool horz = sb->orientation() == QScrollBar::Horizontal;

// b表示间隙,向下箭头|向上箭头的宽度比滚动条的宽度小2*b

    int b = 2;

    int w = horz ? sb->height() : sb->width();

    QColorGroup g = sb->colorGroup();

int sliderMin, sliderMax, sliderLength, buttonDim;

// 下面代码获取的尺寸中最重要的是sliderLength,即滑块高度

// buttonDim表示向下箭头|向上箭头的高度,默认为滚动条的宽度

// 如果垂直滚动条的高度太小,buttonDim就为其高度的一半

scrollBarMetrics( sb, sliderMin, sliderMax, sliderLength, buttonDim );

if (sliderStart > sliderMax)

{ // sanity check

              sliderStart = sliderMax;

    }

bool maxedOut = (sb->maxValue() == sb->minValue());

// 绘制向下的箭头

if ( controls & AddLine )

{

              bool sunken = activeControl & AddLine;

        // 确定箭头所在的矩形区域

              QRect r( b, b, w-2*b, w-2*b ) ;

              if ( horz )

                  r.moveBy( sb->width() - w, 0 );

              else

          r.moveBy( 0, sb->height() - w );

              drawMetalButton( p, r.x(), r.y(), r.width(), r.height(),sunken, !horz );

              drawArrow( p, horz ? RightArrow : DownArrow, sunken,

                       r.x(), r.y(), r.width(), r.height(), g, !maxedOut );

}

// 绘制向上的箭头

if ( controls & SubLine )

{

              bool sunken = activeControl & SubLine;

        // 确定箭头所在的矩形区域

              QRect r( b, b, w-2*b, w-2*b ) ;

              drawMetalButton( p, r.x(), r.y(), r.width(), r.height(),sunken, !horz );

              drawArrow( p, horz ? LeftArrow : UpArrow, sunken,

                          r.x(), r.y(), r.width(), r.height(), g, !maxedOut );

}       

// 确定滑块所在的矩形区域

    QRect sliderR;

if ( horz )

{

              sliderR .setRect( sliderStart, b, sliderLength, w-2*b );

}

else

{

              sliderR .setRect( b, sliderStart, w-2*b, sliderLength );

    }

if ( controls & Slider )

{

    // 绘制滑块,这里是套用绘制按钮的方式

              if ( !maxedOut )

{

                     drawMetalButton( p, sliderR.x(), sliderR.y(), sliderR.width(), sliderR.height(),

FALSE, horz );

}

    }

}

       这个例子比较简单,省略了很多dd。比如:如果滚动条的高度不到滚动条宽度的两倍,那么向下箭头|向上箭头的尺寸就不能是(w-2*b, w-2*b),而应该是:(w-2*b, buttonDim).

如果要绘制的滑块比较复杂,比如分为三段,就要调整代码了,例如:

QPixmap blockTop = Resource::loadPixmap("arrow_top.png");

QPixmap blockBot = Resource::loadPixmap("arrow_bot.png");

QPixmap blockMid =Resource::loadPixmap("block_mid.png");

QPixmap blockEdge = Resource::loadPixmap("block_edge.png");

int sh = sliderR.height() - blockBot.height() - blockTop.height() - 1;

// 如果滑块高度 > 滑块头高度+滑块尾高度+滑块中间高度

if (sh > blockMid.height())

{

    // 画滑块背景,blockEdge的高度只有1,所以要进行拉伸

       p->drawTiledPixmap(sliderR.x(), sliderR.y()+blockBot.height(),

                                   sliderR.width(), sh, blockBg );

    // 画滑块中间部分

       p->drawPixmap(sliderR.x(),sliderR.y() + blockBot.height() +

(sh - blockMid.height())/2, blockMid);

}

else //滑块高度不够,直接画背景

{

       p->drawPixmap(sliderR.x(), sliderR.y() + blockBot.height(),blockMid, 0,

(blockMid.height() - sh) / 2, sliderR.width(), sh);

}

// 画头和尾,即滑块的最上/下部,一般为椭圆性过渡

p->drawPixmap(sliderR.x(), sliderR.y(), blockTop);

p->drawPixmap(sliderR.x(), sliderR.bottom() - blockBot.height(), blockBot);

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值