QT使用QWidget绘制圆角窗口
1. 使用QSS样式绘制
正常情况下
QWIDget
是不支持
border-radius
样式属性的,但可以通过添加
Qt::WA_TranslucentBackground
来使其支持
border-radius
。
属性设置代码如下:
// Qt::FramelessWindowHint 使窗口不使用默认框架如关闭最大最小化等// Qt::Dialog 由于我这里的窗口是继承自QDialog的,如果这里不设置此属性,在创建窗口时传入parent指针,exec()会显示不出来窗口setWindowFlags(Qt::FramelessWindowHint | Qt::Dialog);// 设置窗口透明永用来支持圆角样式属性setAttribute(Qt::WA_TranslucentBackground);
QStringList qss;// 全局背景 角度
qss <<"#About{background-color:#FFFFFF;border-radius:4px;}";setStyleSheet(qss.join(""));
Qt::WA_TranslucentBackground
的作用是可以使窗体背景透明,而其中部件不受影响,而此时若要设置窗口的样式则要重
paintEvent(QPaintEvent *event)
1.1 重写paintEvent
绘制窗口背景颜色显示代码如下:
voidAbout::paintEvent(QPaintEvent *event){// 指定样式操作对象// QStyleOption及其子类包含QStyle函数绘制图形元素所需的所有信息
QStyleOption opt;// 指定要绘制this对象的样式
opt.init(this);// 创建绘制对象,this为最终要进行绘制的对象
QPainter painter(this);/*
* drawPrimitive
* 使用option指定的样式,绘制painter指定的对象
* QStyle::PE_Widget 标识要绘制的原始元素
*/style()->drawPrimitive(QStyle::PE_Widget,&opt,&painter,this);}
1.1 不重写paintEvent的实现方式
此方式需要在
Widget(About)
中在放置一个
Widget(foreground)
,但本质上还是依赖于
Qt::WA_TranslucentBackground
。
将
About
设置如下属性:
setWindowFlags(Qt::FramelessWindowHint | Qt::Dialog);setAttribute(Qt::WA_TranslucentBackground);
使用
QGraphicsDropShadowEffect
设置
foreground
的阴影及圆角,同时使用
border-radius
属性设置
foreground
的圆角:
//实例阴影shadow
QGraphicsDropShadowEffect *shadow =newQGraphicsDropShadowEffect(this);//设置阴影距离
shadow->setOffset(0,0);//设置阴影颜色
shadow->setColor(QColor("#444444"));//设置阴影圆角
shadow->setBlurRadius(6);
ui->forground->setStyleSheet("#forground{background-color:#FFFFFF;border-radius:6px;}");/*
* setGraphicsEffect(shadow); 会触发UpdateLayeredWindowIndirect failed for ptDst= ..... (参数错误)
*/
ui->forground->setGraphicsEffect(shadow);
1.2 总结
- 第一步设置窗口属性
- 第二步重新绘制窗口样式
2. 使用paintEvent绘制
总体步骤与第一种方式的步骤一致。
属性设置代码如下:
setWindowFlags(Qt::FramelessWindowHint | Qt::Dialog);setAttribute(Qt::WA_TranslucentBackground);
绘制窗口显示代码如下:
voidAbout::paintEvent(QPaintEvent *event){// 创建绘图对象,并指定this为“画板”
QPainter painter(this);/*
* setRenderHint:设置渲染属性
* QPainter::Antialiasing:表示如果可能,引擎应该对图元的边缘进行抗锯齿处理
*/
painter.setRenderHint(QPainter::Antialiasing);/*
* Brush用于填充背景
*/
painter.setBrush(QColor(255,255,255));// Pen 用于绘制轮廓线
painter.setPen(Qt::transparent);// 获取绘制区域
QRect rect =this->rect();// 设置绘制区域宽度
rect.setWidth(rect.width());// 设置绘制区域高度
rect.setHeight(rect.height());/*
* drawRoundedRect 绘制带圆角的矩形
*/
painter.drawRoundedRect(rect,4,4);QWidget::paintEvent(event);}
3. 增加鼠标拖动事件
为了使无框架窗口捕获事件需要安装事件捕获,以便捕获各种事件。
安装事件过滤器:
installEventFilter(this);
捕获事件进行处理:
boolAbout::eventFilter(QObject *watched, QEvent *evt){// 鼠标位置static QPoint mousePoint;// 是否按下标记staticbool mousePressed =false;// 将事件转换为鼠标事件
QMouseEvent *event =static_cast<QMouseEvent *>(evt);// 鼠标按下if(event->type()== QEvent::MouseButtonPress){// 左键按下if(event->button()== Qt::LeftButton){// 设置按下标记为true
mousePressed =true;/*
* this->pos() 获取此窗口在父窗口中的位置
* event->globalPos() 鼠标按下时的全局位置
* mousePoint 鼠标按下时在此窗口中的位置
*/
mousePoint = event->globalPos()-this->pos();returntrue;}else{exit(0);}}elseif(event->type()== QEvent::MouseButtonRelease){
mousePressed =false;returntrue;}elseif(event->type()== QEvent::MouseMove){if(mousePressed &&(event->buttons()&& Qt::LeftButton)){/*
* 移动窗口
*/this->move(event->globalPos()- mousePoint);returntrue;}}returnQWidget::eventFilter(watched, event);}
4. Demo
使用border-radius属性方式一
使用border-radius属性方式二
不使用border-radius属性方式
版权归原作者 愤怒的小黄鸭 所有, 如有侵权,请联系我们删除。