Qt自定义滚动条(不使用样式表)
前面使用Qt 样式表实现滚动条,在实际工作中,发现存在一些瑕疵,例如如果在主窗口中绘制背景,则有可能给滚动条染色,还有如果想实现特殊的效果,则必须使用自定义风格,即从QStyle的子类派生出新的类型。以下从QProxyStyl派生出新的风格来实现自定义滚动(Qt4、Qt5均存在QCommonStyle、QProxyStyle,其余的风格在Qt5中已经不存在,不过原理一致)。
首先QScrollbar重绘时直接调用
drawComplexControl( ComplexControl control, const QStyleOptionComplex *option, QPainter *painter, const QWidget *widget ) const
由此开始我们的自定绘制滚动条:
void MyStyle::drawComplexControl( ComplexControl control, const QStyleOptionComplex *option, QPainter *painter, const QWidget *widget ) const
{
switch (control)
{
case CC_ScrollBar:
drawScrollbar(control, option, painter, widget);
return;
default:
break;
}
__super::drawComplexControl(control, option, painter, widget);
}
绘制代码的实现(模拟QQ)
void MyStyle::drawScrollbar( ComplexControl control, const QStyleOptionComplex *option, QPainter *painter, const QWidget *widget ) const
{
//QQ中滚动条的效果是:如果不在滚动条上,默认上下箭头不显示,AddPage, SubPage也不显示。
//如果在滚动条上,如果不在箭头所在的区域,则显示normal,否则显示hot,按下显示down。
//这里按这个标准实现。
const QStyleOptionSlider *scrollbar = qstyleoption_cast<const QStyleOptionSlider *>(option);
if(!scrollbar) return;
bool maxedOut = (scrollbar->maximum == scrollbar->minimum);
if(maxedOut) return; painter->save();
painter->setRenderHint(QPainter::Antialiasing);
QRect r = option->rect; const State state = option->state;
const SubControls sub = option->subControls; State flags = option->state;
if (widget && widget->testAttribute(Qt::WA_UnderMouse) && widget->isActiveWindow())
flags |= State_MouseOver; QRect drawRect; if (maxedOut)
flags &= ~State_Enabled; const bool pressed = flags & State_Sunken;
const bool mouseOver = flags & State_MouseOver;
const bool isHorz = flags & State_Horizontal;
const bool isRTL = option->direction == Qt::RightToLeft; QColor bkFillColor = Qt::white;
QColor bkSliderNormal = Qt::lightGray;
QColor bkSliderHover = Qt::gray;
QColor bkSliderPress = Qt::darkGray; //清除所有子控件背景
//上下(左右)箭头可能和沟槽的背景不一样
drawRect= subControlRect(CC_ScrollBar, option, SC_ScrollBarAddLine, widget);
painter->fillRect(drawRect, bkFillColor); drawRect= subControlRect(CC_ScrollBar, option, SC_ScrollBarSubLine, widget);
painter->fillRect(drawRect, bkFillColor); //沟槽的颜色
drawRect = subControlRect(CC_ScrollBar, option, SC_ScrollBarGroove, widget);
painter->fillRect(drawRect, Qt::green);
//在mouse over状态下,才绘制上下左右箭头。
//scrollbar->activeSubControls用于指定当前鼠标所在的子控件
const QStyle::SubControls sc = scrollbar->activeSubControls;
if(!mouseOver)
{
//只绘制Slider,其余清除
drawRect = subControlRect(CC_ScrollBar, option, SC_ScrollBarSlider, widget); QPainterPath painterPath;
painterPath.addRoundedRect(drawRect.left(), drawRect.top(), drawRect.width(), drawRect.height(), , );
painter->fillPath(painterPath, bkSliderNormal);
}
else
{
//合并绘制AddPage SubPage
drawRect = subControlRect(CC_ScrollBar, option, SC_ScrollBarGroove, widget);
painter->fillRect(drawRect, QColor(, , , )); if (sub & SC_ScrollBarAddLine) //画加号,应该区分水平和垂直
{
drawRect= subControlRect(CC_ScrollBar, option, SC_ScrollBarAddLine, widget);
QPixmap pixmap;
if(isHorz)
{
if(pressed) pixmap.load(":/ScrollBar/scrollbar_arrowright_down.png");
else if(sc & SC_ScrollBarAddLine) pixmap.load(":/ScrollBar/scrollbar_arrowright_highlight.png");
else pixmap.load(":/ScrollBar/scrollbar_arrowright_normal.png");
}
else
{
if(pressed) pixmap.load(":/ScrollBar/scrollbar_arrowdown_down.png");
else if(sc & SC_ScrollBarAddLine) pixmap.load(":/ScrollBar/scrollbar_arrowdown_highlight.png");
else pixmap.load(":/ScrollBar/scrollbar_arrowdown_normal.png");
} painter->drawPixmap(drawRect, pixmap);
}
if (sub & SC_ScrollBarSubLine)
{
drawRect= subControlRect(CC_ScrollBar, option, SC_ScrollBarSubLine, widget);
QPixmap pixmap; if(isHorz)
{
if(pressed) pixmap.load(":/ScrollBar/scrollbar_arrowleft_down.png");
else if(sc & SC_ScrollBarSubLine) pixmap.load(":/ScrollBar/scrollbar_arrowleft_highlight.png");
else pixmap.load(":/ScrollBar/scrollbar_arrowleft_normal.png");
}
else
{
if(pressed) pixmap.load(":/ScrollBar/scrollbar_arrowup_down.png");
else if(sc & SC_ScrollBarSubLine) pixmap.load(":/ScrollBar/scrollbar_arrowup_highlight.png");
else pixmap.load(":/ScrollBar/scrollbar_arrowup_normal.png");
} painter->drawPixmap(drawRect, pixmap);
}
if (sub & SC_ScrollBarSlider)
{
drawRect = subControlRect(CC_ScrollBar, option, SC_ScrollBarSlider, widget); QPainterPath painterPath;
painterPath.addRoundedRect(drawRect.left(), drawRect.top(), drawRect.width(), drawRect.height(), , );
if(sc & SC_ScrollBarSlider)
{
painter->fillPath(painterPath, bkSliderPress);
}
else
{
painter->fillPath(painterPath, bkSliderHover);
}
} }
painter->restore();
}
效果如下:

左为鼠标不在滚动条区域,右边为鼠标在滚动条区域
这里使用绿色做沟槽的背景,方便调试。
Qt自定义滚动条(不使用样式表)的更多相关文章
- PyQt(Python+Qt)学习随笔:Qt Designer中部件的样式表styleSheet属性
styleSheet属性是定义部件外观的属性样式表,在Qt中styleSheet样式表是类似于html的css样式一样的方法,只是时专门为Qt中的部件开发的.styleSheet的定义语法也是类似CS ...
- Qt 自定义 滚动条 样式
今天是时候把软件中的进度条给美化美化了,最初的想法就是仿照QQ. 先前的进度条是这样,默认的总是很难受欢迎的:美化之后的是这样,怎么样?稍微好看一点点了吧,最后告诉你实现这个简单的效果在Qt只需要加几 ...
- Qt 自定义 滚动条 样式(模仿QQ)
今天是时候把软件中的进度条给美化美化了,最初的想法就是仿照QQ. 先前的进度条是这样,默认的总是很难受欢迎的:美化之后的是这样,怎么样?稍微好看一点点了吧,最后告诉你实现这个简单的效果在Qt只需要加几 ...
- QT样式表
QT样式表 一.QT样式表简介 1.QT样式表简介 QSS的主要功能是使界面的表现与界面的元素分离,使得设计皮肤与界面控件分离的软件成为可能. QT样式表是允许用户定制widgets组件外观的强大机制 ...
- Qt样式表的使用
Qt中可以灵活的使用层叠样式表(CSS),其语法和CSS很相似.因为HTML CSS的灵活性,所以可以很方便的为QT界面设计自己需要的外观.除了子类化Style类,使用QT样式表(QStyleShee ...
- WPF ScrollViewer(滚动条) 自定义样式表制作 再发一套样式 细节优化
艾尼路 出的效果图 本人嵌套 WPF ScrollViewer(滚动条) 自定义样式表制作 图文并茂 WPF ScrollViewer(滚动条) 自定义样式表制作 (改良+美化) 源代码
- WPF ScrollViewer(滚动条) 自定义样式表制作 图文并茂
原文:WPF ScrollViewer(滚动条) 自定义样式表制作 图文并茂 先上效果图 正常样式 拖动时样式 好下面 开始吧 ==================================== ...
- WPF ScrollViewer(滚动条) 自定义样式表制作 (改良+美化)
原文:WPF ScrollViewer(滚动条) 自定义样式表制作 (改良+美化) 注释直接写在代码里了 不太理解意思的 可以先去看看我上一篇 WPF ScrollViewer(滚动条) 自定 ...
- Qt StyleSheet样式表实例(转)
QT论坛看到的,收藏一下! 在涉及到Qt 美工的时候首先需要掌握CSS 级联样式表. 下面将通过几个例子来介绍一下怎样使用Qt中的部件类型设计.自定义的前台背景与后台背景的颜色: 如果需要一个文本编辑 ...
随机推荐
- pycharm中运行成功的python代码在jenkin中运行问题总结
我们在用selenium+python完成了项目的UI自动化后,一般用jekins持续集成工具来定期运行,python程序在pycharm中编辑运行成功,但在jenkins中运行失败的两个问题,整理如 ...
- 2018-2019-2 网络对抗技术 20165304 Exp6 信息搜集与漏洞扫描
2018-2019-2 网络对抗技术 20165304 Exp6 信息搜集与漏洞扫描 原理与实践说明 1.实践原理 信息搜集:渗透测试中首先要做的重要事项之一,搜集关于目标机器的一切信息 间接收集 D ...
- python3集合练习(set)
#集合是由不同元素组成;无序;集合中的元素必须是不可变类型;#s = {} 或者 s = set() 创建集合#update()扩展集合.返回值为Noneg1 = {'wcj','good','luc ...
- HTML - form (转)
自:http://www.runoob.com <form> 标签 标签定义及使用说明 <form> 标签用于创建供用户输入的 HTML 表单. <form> 元素 ...
- Traceback (most recent call last): File "c:\program files (x86)\microsoft visual studio\2019\community\common7\ide\extensions\microsoft\python\core\Packages\ptvsd\_vendored\pydevd\_pydevd_bundle\pyd
某次编码,debug的时候突然突然突然给我报这个错: Traceback (most recent call last): File "c:\program files (x86)\mi ...
- Dynamic Method Binding in Delphi 动态方法绑定
Dynamic Method Binding in Delphi 动态方法绑定 https://docs.dataabstract.com/Delphi/AdvancedTopics/Dynamic ...
- hibernate的开始
1.1对象的持久化 对象持久化是指将内存中的对象保存到可永久保存的存储设备中(如磁盘)的一种技术.(hibernate是通过id来管理对象) 1.2怎样实现持久化 1 对象序列化 2 JDBC 3 O ...
- ADDED、ADDED_TO_STAGE、REMOVED、REMOVED_FROM_STAGE这几个事件的区别
var _container:Sprite = new Sprite(); _container.addEventListener(Event.ADDED,onAdded); _container.a ...
- base64位代码转图片文件并保存到文件夹的解决方案
#region Base64 转图片方法 protected string Base64StringToImage(string strbase64) { try { string imgurl = ...
- jq动画设置图片抽奖
(因为自己是前端刚入门的小白所以中间出现很多问题,不过这对于我来说就是一次经验的积累) 预想效果:点击"开始",图片循环旋转,不是同时的效果,而是有一定的时间差.点击"开 ...