Qt源码分享(一)-- 圆角+阴影+可移动+大小可变
关注微信公众号在菜单栏获取源码
由于自己项目的需要,主界面需要实现圆角+阴影+可移动+拖拽可变大小。一看到这样的功能,立马就开始百度。结果百度了快一天都没有找到合适的,虽然能够实现圆角或者阴影的,但是实现的方式总觉得不太合适。最后还是高人赵哥把源码给我了,我又在网络上搜索了一番加上拖拽可变大小的功能。
好,我们先看下效果:
为了对原作者的尊重,头文件的作者我就保留了下。
拖拽可变大小我是参考这里的:https://www.cnblogs.com/xufeiyang/p/3313104.html
头文件的实现:
/*!
* @file mainwindow.h
* @author ZhaoYanbo
* @date 2019-10-29
* @details ...
* @version v1.0.0
*/
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QDialog>
#include <QWidget>
class MainWindow : public QWidget
{
Q_OBJECT
enum Direction{
UP = 0,
DOWN,
LEFT,
RIGHT,
LEFTTOP,
LEFTBOTTOM,
RIGHTBOTTOM,
RIGHTTOP,
NONE
};
public:
explicit MainWindow(QWidget *parent = nullptr);
~MainWindow();
public:
void SetResizeable(bool isResize);
bool IsResizeable() const;
void SetRadius(bool radius);
int GetRadius() const;
protected:
void resizeEvent(QResizeEvent *) override;
void paintEvent(QPaintEvent *) override;
void mouseReleaseEvent(QMouseEvent *event);
void mouseMoveEvent(QMouseEvent *event);
void mousePressEvent(QMouseEvent *event);
private:
void region(const QPoint &cursorPoint);
/*!
* \brief 绘制带尖的图片
* \param w 图片宽度
* \param h 图片高度
* \param tip_w 尖的宽度
* \param tip_h 尖的高度
* \param radius 矩形圆角半径
* \param margin 边距
* \return
*/
QPixmap drawTip(const int w, const int h, const int tip_w, const int tip_h,
const int radius, const int margin);
private:
QPixmap m_pixmap;
bool mIsLeftPressDown;
QPoint mDragPosition;
Direction mDirec;
bool mResizeable;
int mRadius;
};
#endif // MAINWINDOW_H
实现的部分cpp文件:
#include "mainwindow.h"
#include <QGraphicsBlurEffect>
#include <QPainter>
#include <QResizeEvent>
static const int SHADOW_WIDTH = 16;
#define PADDING 18
#define PADDING_TOP 29
MainWindow::MainWindow(QWidget *parent) : QWidget(parent)
{
mIsLeftPressDown = false;
this->mResizeable = true;
this->mDirec = NONE;
this->mRadius = 4;
this->setMouseTracking(true);
QGraphicsDropShadowEffect* pShadowEffect = new QGraphicsDropShadowEffect(this);
pShadowEffect->setOffset(0, 0);
pShadowEffect->setColor(Qt::lightGray);
pShadowEffect->setBlurRadius(SHADOW_WIDTH);
this->setGraphicsEffect(pShadowEffect);
this->setAttribute(Qt::WA_TranslucentBackground, true);
this->setWindowFlags(this->windowFlags() | Qt::FramelessWindowHint);
}
MainWindow::~MainWindow()
{}
void MainWindow::SetResizeable(bool isResize)
{
mResizeable = isResize;
}
bool MainWindow::IsResizeable() const
{
return mResizeable;
}
void MainWindow::SetRadius(bool radius)
{
mRadius = radius;
}
int MainWindow::GetRadius() const
{
return mRadius;
}
void MainWindow::resizeEvent(QResizeEvent *e)
{
const QSize s = e->size();
int w = s.width();
int h = s.height();
if(w > 1 && h > 1) {
m_pixmap = drawTip(w, h, 18, 12, mRadius, SHADOW_WIDTH);
}
}
void MainWindow::paintEvent(QPaintEvent *)
{
if(m_pixmap.isNull())
return;
QPainter p;
p.begin(this);
p.drawPixmap(this->rect(), m_pixmap);
p.end();
}
void MainWindow::region(const QPoint &cursorGlobalPoint)
{
QRect rect = this->rect();
QPoint tl = mapToGlobal(rect.topLeft());
QPoint rb = mapToGlobal(rect.bottomRight());
int x = cursorGlobalPoint.x();
int y = cursorGlobalPoint.y();
if(tl.x() + PADDING_TOP >= x && tl.x() <= x && tl.y() + PADDING_TOP >= y && tl.y() <= y) {
// 左上角
mDirec = LEFTTOP;
this->setCursor(QCursor(Qt::SizeFDiagCursor));
} else if(x >= rb.x() - PADDING && x <= rb.x() && y >= rb.y() - PADDING && y <= rb.y()) {
// 右下角
mDirec = RIGHTBOTTOM;
this->setCursor(QCursor(Qt::SizeFDiagCursor));
} else if(x <= tl.x() + PADDING && x >= tl.x() && y >= rb.y() - PADDING && y <= rb.y()) {
//左下角
mDirec = LEFTBOTTOM;
this->setCursor(QCursor(Qt::SizeBDiagCursor));
} else if(x <= tl.x() + PADDING && x >= tl.x()) {
// 左边
mDirec = LEFT;
this->setCursor(QCursor(Qt::SizeHorCursor));
} else if( x <= rb.x() && x >= rb.x() - PADDING) {
// 右边
mDirec = RIGHT;
this->setCursor(QCursor(Qt::SizeHorCursor));
}else if(y >= tl.y() && y <= tl.y() + PADDING_TOP){
// 上边
mDirec = UP;
this->setCursor(QCursor(Qt::SizeVerCursor));
} else if(y <= rb.y() && y >= rb.y() - PADDING) {
// 下边
mDirec = DOWN;
this->setCursor(QCursor(Qt::SizeVerCursor));
}else {
// 默认
mDirec = NONE;
this->setCursor(QCursor(Qt::ArrowCursor));
}
}
QPixmap MainWindow::drawTip(const int w, const int h, const int tip_w, const int tip_h, const int radius, const int margin)
{
const int w2 = w - margin * 2 - radius * 2 - tip_w;
QPainterPath path;
// TODO 关注微信公众号:cpp手艺人
return pixmap;
}
void MainWindow::mouseReleaseEvent(QMouseEvent *event)
{
if(event->button() == Qt::LeftButton) {
mIsLeftPressDown = false;
if(mDirec != NONE) {
this->releaseMouse();
this->setCursor(QCursor(Qt::ArrowCursor));
}
}
}
void MainWindow::mousePressEvent(QMouseEvent *event)
{
switch(event->button()) {
case Qt::LeftButton:
mIsLeftPressDown = true;
if(mDirec != NONE) {
this->mouseGrabber();
} else {
mDragPosition = event->globalPos() - this->frameGeometry().topLeft();
}
break;
default:
QWidget::mousePressEvent(event);
}
}
void MainWindow::mouseMoveEvent(QMouseEvent *event)
{
QPoint gloPoint = event->globalPos();
QRect rect = this->rect();
QPoint tl = mapToGlobal(rect.topLeft());
QPoint rb = mapToGlobal(rect.bottomRight());
if(!mIsLeftPressDown) {
if (mResizeable) {
this->region(gloPoint);
}
} else {
if(mDirec != NONE && mResizeable) {
QRect rMove(tl, rb);
switch(mDirec) {
case LEFT:
if(rb.x() - gloPoint.x() <= this->minimumWidth())
rMove.setX(tl.x() - SHADOW_WIDTH);
else
rMove.setX(gloPoint.x() - SHADOW_WIDTH);
break;
case RIGHT:
rMove.setWidth(gloPoint.x() - tl.x() + SHADOW_WIDTH);
break;
case UP:
if(rb.y() - gloPoint.y() <= this->minimumHeight())
rMove.setY(tl.y() - PADDING_TOP);
else
rMove.setY(gloPoint.y() - PADDING_TOP);
break;
case DOWN:
rMove.setHeight(gloPoint.y() - tl.y() + SHADOW_WIDTH);
break;
case LEFTTOP:
if(rb.x() - gloPoint.x() <= this->minimumWidth())
rMove.setX(tl.x() - PADDING);
else
rMove.setX(gloPoint.x() - PADDING);
if(rb.y() - gloPoint.y() <= this->minimumHeight())
rMove.setY(tl.y() - PADDING_TOP);
else
rMove.setY(gloPoint.y() - PADDING_TOP);
break;
default:
break;
}
this->setGeometry(rMove);
} else {
move(event->globalPos() - mDragPosition);
event->accept();
}
}
QWidget::mouseMoveEvent(event);
}
最后,如果这段源码帮助了你,节省了你的时间,请打赏下吧。我们不要5块,10块,只要1、2块,这段代码抱回家。让你早点下班,吃上热饭,保住头发。
大家拿到了源码,自己在封装封装,加入到自己的类库中,为以后的开发绝对节省不少时间。
关于赞赏,因为我跟赵哥说过了,大家打赏的都是他的。感谢大家对原创的支持。
关注微信公众号:菜单-》Qt源码分享
ent->globalPos() - mDragPosition);
event->accept();
}
}
QWidget::mouseMoveEvent(event);
}
最后,如果这段源码帮助了你,节省了你的时间,请打赏下吧。我们不要5块,10块,只要1、2块,这段代码抱回家。让你早点下班,吃上热饭,保住头发。
大家拿到了源码,自己在封装封装,加入到自己的类库中,为以后的开发绝对节省不少时间。
关于赞赏,因为我跟赵哥说过了,大家打赏的都是他的。感谢大家对原创的支持。
**关注微信公众号:菜单-》Qt源码分享**