Files
Renderive/Widget/component/frameless/Frame_Less_Widget.cpp
T
2026-07-29 18:08:57 +08:00

239 lines
8.2 KiB
C++

#include "Frame_Less_Widget.h"
#include <QMouseEvent>
#include <QPainter>
#include <QScreen>
#include <qmath.h>
using change_size = std::function<void(void)>;
Frame_Less_Widget::Frame_Less_Widget(QWidget* parent) : QWidget(parent) {
setMouseTracking(true);
setAttribute(Qt::WA_Hover);
setAttribute(Qt::WA_TranslucentBackground);
// setAttribute(Qt::WA_Mapped);
setWindowFlags(
Qt::Window |
Qt::FramelessWindowHint |
Qt::WindowSystemMenuHint |
Qt::WindowMinimizeButtonHint |
Qt::WindowMaximizeButtonHint);
space = 0;
radius = 16;
top_margin = 16;
bottom_margin = 16;
right_margin = 16;
left_margin = 16;
shapes = {Qt::SizeFDiagCursor, Qt::SizeVerCursor, Qt::SizeBDiagCursor,
Qt::SizeHorCursor, Qt::ArrowCursor, Qt::SizeHorCursor,
Qt::SizeBDiagCursor, Qt::SizeVerCursor, Qt::SizeFDiagCursor,
Qt::ArrowCursor};
change_sizes = {[this]() {
// R11
setGeometry(start_x + dx, start_y + dy, qMax(start_w - dx, get_min_width()), qMax(start_h - dy, get_min_height()));
},
[this]() {
// R12
setGeometry(start_x, start_y + dy, qMax(start_w, get_min_width()), qMax(start_h - dy, get_min_height()));
},
[this]() {
// R13
setGeometry(start_x, start_y + dy, qMax(start_w + dx, get_min_width()), qMax(start_h - dy, get_min_height()));
},
[this]() {
// R21
setGeometry(start_x + dx, start_y, qMax(start_w - dx, get_min_width()), qMax(start_h, get_min_height()));
},
[]() {
// R22
},
[this]() {
// R23
setGeometry(start_x, start_y, qMax(start_w + dx, get_min_width()), qMax(start_h, get_min_height()));
},
[this]() {
// R31
setGeometry(start_x + dx, start_y, qMax(start_w - dx, get_min_width()), qMax(start_h + dy, get_min_height()));
},
[this]() {
// R32
setGeometry(start_x, start_y, qMax(start_w, get_min_width()), qMax(start_h + dy, get_min_height()));
},
[this]() {
// R33
setGeometry(start_x, start_y, qMax(start_w + dx, get_min_width()), qMax(start_h + dy, get_min_height()));
},
[]() {
// null
}};
}
int Frame_Less_Widget::get_min_width() {
return 0;
}
int Frame_Less_Widget::get_min_height() {
return 0;
}
void Frame_Less_Widget::paintEvent(QPaintEvent* event) {
QPainter painter(this);
painter.setRenderHint(QPainter::Antialiasing);
painter.fillRect(rect(), QColor(255, 255, 255, 1)); // 不能改 让他不是透明的 // painter.fillRect(r11, Qt::blue);
// painter.fillRect(r12, Qt::darkCyan);
// painter.fillRect(r13, Qt::green);
// painter.fillRect(r21, Qt::gray);
// painter.fillRect(r22, Qt::red);
// painter.fillRect(r23, Qt::darkGreen);
// painter.fillRect(r31, Qt::black);
// painter.fillRect(r32, Qt::darkRed);
// painter.fillRect(r33, Qt::darkBlue); 否则改变大小失效
// https://blog.csdn.net/liushuaitong/article/details/122117384
// https://www.cnblogs.com/linuxAndMcu/p/11057347.html
QRect rect = r22;
// painter.drawRoundedRect(rect, radius, radius);
// 画阴影边框
auto color = background_color;
// int x_radius = r22.width();
// int y_radius = r22.height();
int x_radius = radius;
int y_radius = radius;
int mul = 2;
int n = top_margin / mul;
auto max = double(n * n * n);
double value = background_color.alpha();
for (int i = 0; i < n; i++) {
if (i == 0) {
painter.setPen(Qt::NoPen);
QColor b = QColor::fromRgb(background_color.red(), background_color.green(), background_color.blue());
painter.setBrush(b);
painter.drawRoundedRect(rect, x_radius, y_radius);
painter.setBrush(Qt::NoBrush);
}
else {
double rate = (i * i * i) / max;
color.setAlpha(static_cast<int>(value * (1 - rate)));
painter.setBrush(color);
painter.drawRoundedRect(rect.adjusted(-i * mul, -i * mul, i * mul, i * mul), x_radius, y_radius);
}
}
painter.end();
}
bool Frame_Less_Widget::event(QEvent* event) {
if (event->type() == QEvent::HoverMove) {
auto* hover_event = static_cast<QHoverEvent*>(event);
// qDebug() << hover_event->pos();
QMouseEvent mouse_event(QEvent::MouseMove, hover_event->pos(),
Qt::NoButton, Qt::NoButton, Qt::NoModifier);
mouseMoveEvent(&mouse_event);
}
return QWidget::event(event);
}
void Frame_Less_Widget::set_pos() {
x1 = 0;
x2 = x1 + left_margin + space;
x3 = width() - right_margin - space;
y1 = 0;
y2 = y1 + top_margin + space;
y3 = height() - bottom_margin - space;
}
void Frame_Less_Widget::set_rs() {
int w1 = x2 - x1, w2 = x3 - x2, w3 = width() - x3;
int h1 = y2 - y1, h2 = y3 - y2, h3 = height() - y3;
r11.setRect(x1, y1, w1, h1);
r12.setRect(x2, y1, w2, h1);
r13.setRect(x3, y1, w3, h1);
r21.setRect(x1, y2, w1, h2);
r22.setRect(x2, y2, w2, h2);
r23.setRect(x3, y2, w3, h2);
r31.setRect(x1, y3, w1, h3);
r32.setRect(x2, y3, w2, h3);
r33.setRect(x3, y3, w3, h3);
}
void Frame_Less_Widget::mousePressEvent(QMouseEvent* event) {
auto pos = event->pos();
if (event->button() != Qt::LeftButton)
return;
if (changing_size)
return;
if (drag_moving)
return;
cur_r = get_rect_type(pos);
if (cur_r != Drag_R) {
changing_size = true;
setCursor(shapes[cur_r]);
}
else {
drag_moving = true;
setCursor(Qt::ClosedHandCursor);
}
if (changing_size || drag_moving) {
start_x = this->x();
start_y = this->y();
start_global_x = event->globalPos().x();
start_global_y = event->globalPos().y();
start_w = width();
start_h = height();
}
}
void Frame_Less_Widget::mouseReleaseEvent(QMouseEvent* event) {
if (changing_size) {
changing_size = false;
}
if (drag_moving) {
drag_moving = false;
setCursor(Qt::OpenHandCursor);
}
}
void Frame_Less_Widget::mouseMoveEvent(QMouseEvent* event) {
Rect_Type ret = get_rect_type(event->pos());
if (ret == Drag_R) {
if (!drag_moving) {
setCursor(Qt::OpenHandCursor);
}
}
else {
setCursor(shapes[ret]);
}
if (!changing_size && !drag_moving) {
return;
}
const QPoint& cur_global_pos = event->globalPos();
dx = cur_global_pos.x() - start_global_x;
dy = cur_global_pos.y() - start_global_y;
if (changing_size) {
change_sizes[cur_r]();
}
else if (drag_moving) {
move(start_x + dx, start_y + dy);
}
}
Rect_Type Frame_Less_Widget::get_rect_type(const QPoint& p) const {
if (p.y() < y2) {
if (p.x() < x2)
return R11;
if (p.x() > x3)
return R13;
if (p.x() < (x2 + x3) / 4)
return Drag_R;
return R12;
}
if (p.y() > y3) {
if (p.x() < x2)
return R31;
if (p.x() > x3)
return R33;
return R32;
}
if (p.x() < x2)
return R21;
if (p.x() > x3)
return R23;
return R22;
}
void Frame_Less_Widget::resizeEvent(QResizeEvent* event) {
if (isMaximized()) {
QRect screen_size = screen()->availableGeometry().adjusted(-left_margin, -top_margin, right_margin, bottom_margin);
setGeometry(screen_size);
}
set_pos();
set_rs();
}
void Frame_Less_Widget::showEvent(QShowEvent* event) {
QWidget::showEvent(event);
}