Qt绘制圆角矩形半透明窗口

完整的头文件和源文件放在开头,要看说明的可以往后看。
头文件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 一定要加上,不加会导致创建子窗口(已经有一个窗口了,要创建第二个窗口)后,用这两行代码设置后出现的窗口的样式,会导致后出现的窗口只在原有窗口内部显示,如下图:
Qt绘制圆角矩形半透明窗口_第1张图片
接下来开始把窗口变成圆角矩形的形状了。
做法当然是重写绘图事件了,首先在头文件里写上:

// 放在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。
Qt绘制圆角矩形半透明窗口_第2张图片
一个圆角矩形半透明,鼠标拖拽可移动的窗口就完成了。

你可能感兴趣的:(qt,c++,开发语言)