完整的头文件和源文件放在开头,要看说明的可以往后看。
头文件mybasewidget.h
#ifndef MYBASEWIDGET_H
#define MYBASEWIDGET_H
#include
class MyBaseWidget : public QWidget
{
Q_OBJECT
public:
explicit MyBaseWidget(QWidget *parent = nullptr);
private:
void paintEvent(QPaintEvent *);
bool is_pressed;
int press_x;
int press_y;
void mousePressEvent(QMouseEvent *);
void mouseMoveEvent(QMouseEvent *);
void mouseReleaseEvent(QMouseEvent *);
};
#endif // MYBASEWIDGET_H
源文件mybasewidget.cpp
#include "mybasewidget.h"
#include
#include
#define BORDER_COLOR QColor(74, 75, 76, 220)
#define BACKGROUND_COLOR QColor(74, 75, 76, 220)
#define RADIUS 30
MyBaseWidget::MyBaseWidget(QWidget *parent)
: QWidget(parent)
, is_pressed(false)
, press_x(0)
, press_y(0)
{
setWindowFlags(windowFlags() | Qt::FramelessWindowHint);
setAttribute(Qt::WA_TranslucentBackground);
}
void MyBaseWidget::paintEvent(QPaintEvent * ev)
{
QPainter painter(this);
painter.setRenderHint(QPainter::Antialiasing);
QPen pen(BORDER_COLOR);
pen.setWidth(1);
painter.setPen(pen);
QBrush brush(BACKGROUND_COLOR);
painter.setBrush(brush);
QRectF rect(0, 0, this->width(), this->height());
painter.drawRoundedRect(rect, RADIUS, RADIUS);
}
void MyBaseWidget::mousePressEvent(QMouseEvent *ev)
{
is_pressed = true;
auto pos = ev->pos();
press_x = pos.x();
press_y = pos.y();
}
void MyBaseWidget::mouseMoveEvent(QMouseEvent *ev)
{
if (is_pressed)
{
auto global_pos = ev->globalPosition();
move(global_pos.x() - press_x, global_pos.y() - press_y);
}
}
void MyBaseWidget::mouseReleaseEvent(QMouseEvent *)
{
is_pressed = false;
}
首先去掉去掉窗口自带的框架和最小化、关闭等按钮,并把原来窗口的背景去掉(即改为透明色):
setWindowFlags(windowFlags() | Qt::FramelessWindowHint); // 设置窗口为无边框
setAttribute(Qt::WA_TranslucentBackground); // 设置窗口背景透明
注意 setWindowFlags 里的 windowsFlags 一定要加上,不加会导致创建子窗口(已经有一个窗口了,要创建第二个窗口)后,用这两行代码设置后出现的窗口的样式,会导致后出现的窗口只在原有窗口内部显示,如下图:
接下来开始把窗口变成圆角矩形的形状了。
做法当然是重写绘图事件了,首先在头文件里写上:
// 放在public或private里都行
void paintEvent(QPaintEvent *);
源文件里写:
#include // 别忘记包含头文件
// 背景边框颜色,四个参数分别是 红、绿、蓝、不透明度
#define BORDER_COLOR QColor(74, 75, 76, 220)
// 窗口的背景颜色
#define BACKGROUND_COLOR QColor(74, 75, 76, 220)
// 窗口圆角的半径,单位:像素
#define RADIUS 30
void 你的窗口类的类名::paintEvent(QPaintEvent * ev)
{
QPainter painter(this);
painter.setRenderHint(QPainter::Antialiasing); // 设置抗锯齿
QPen pen(BORDER_COLOR);
pen.setWidth(1); // 设置边框为 1 像素
painter.setPen(pen);
QBrush brush(BACKGROUND_COLOR);
painter.setBrush(brush);
QRectF rect(0, 0, this->width(), this->height()); // 画一个和窗口一样大的矩形
painter.drawRoundedRect(rect, RADIUS, RADIUS); // 设置矩形的圆角
}
到这里窗口已经变成圆角半透明的了,但是你肯定会想到原来的窗口标题栏没了,那我们想要移动窗口怎么办呢?那就自己动手写鼠标事件了,代码如下:
窗口类的头文件里写:
int press_x;
int press_y;
void mousePressEvent(QMouseEvent *);
void mouseMoveEvent(QMouseEvent *);
窗口类的源文件里写:
#include // 别忘记包含头文件
void 你的窗口类的类名::mousePressEvent(QMouseEvent *ev)
{
auto pos = ev->pos();
// 用下面两个变量保存鼠标按下时,相对窗口左上角的点的位置
press_x = pos.x();
press_y = pos.y();
}
void 你的窗口类的类名::mouseMoveEvent(QMouseEvent *ev)
{
auto global_pos = ev->globalPosition(); // 鼠标移动时,获取相对于显示器左上角的位置
move(global_pos.x() - press_x, global_pos.y() - press_y);
}
首先在鼠标按下时,记录一下按下的点相对于窗口左上角的相对位置;然后在每次鼠标按下之后移动时,获取移动到的点相对于显示器左上角的位置,用相对于显示器左上角的xy减去鼠标按下的点相对于窗口左上角的xy,即可得到在鼠标移动时我们的窗口该move过去的x和y。
一个圆角矩形半透明,鼠标拖拽可移动的窗口就完成了。