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中的部件类型设计.自定义的前台背景与后台背景的颜色: 如果需要一个文本编辑 ...
随机推荐
- HTML5 使用 JS 生成二维码,带头像
一般在项目开发中,前端显示给用户扫描的二维码基本都是由后端代码生成的,那么这个高大上的功能能不能用 JS 来绘制呢? 答案是肯定的 首先我们需要一个插件 jquery.qrcode.js,该插件基于 ...
- [C#]打包项目[转]
原文:https://www.cnblogs.com/danyu/p/7243706.html 加入自定义操作:https://blog.csdn.net/ristal/article/details ...
- vChart
vue+echarts工具: https://v-charts.js.org
- 【转】How to initialize a two-dimensional array in Python?
[wrong way:] m=[[element] * numcols] * numrows for example: >>> m=[['a'] *3] * 2>>> ...
- [原创] 扩展jquery-treegrid插件, 实现勾选功能和全删按钮.
新上手一个项目, 因而正好想学习下bootstrap, 所以就采用asp.net mvc + bootstrap来做. 因为需要TreeGrid的控件, 本来想用easyUI.LingerUi.DW ...
- Unity3D人脸建模 AvataSDK研究
1.Unity与windows交互 调用文件浏览器 1.用C#调用comdlg32.dll , 利用GetOpenFileName实现打开文件对话框 <1> 整体参考https://w ...
- 移动端目标识别(3)——使用TensorFlow Lite将tensorflow模型部署到移动端(ssd)之Running on mobile with TensorFlow Lite (写的很乱,回头更新一个简洁的版本)
承接移动端目标识别(2) 使用TensorFlow Lite在移动设备上运行 在本节中,我们将向您展示如何使用TensorFlow Lite获得更小的模型,并允许您利用针对移动设备优化 ...
- form表单的三个属性 action 、mothod 、 enctype。
form_action: 表单数据提交到此页面 下面的表单拥有两个输入字段以及一个提交按钮,当提交表单时,表单数据会提交到名为 "form_action.asp" 的页面: < ...
- react 路由之react-router-dom
1安装react-router-dom npm install react-router-dom --save-dev //这里可以使用cnpm代替npm命令 1 新建router文件 //引入 re ...
- rhce 第十题 配置NFS服务
配置NFS服务 在system1配置NFS服务,要求如下: 以只读的方式共享目录/public,同时只能被group8.example.com域中的系统访问 以读写的方式共享目录/protected, ...