这是最终的效果
头文件:
#ifndef WIDGET_H
#define WIDGET_H
#include <QWidget>
#include <QPropertyAnimation>
QT_BEGIN_NAMESPACE
namespace Ui { class Widget; }
QT_END_NAMESPACE
class Widget : public QWidget
{
Q_OBJECT
public:
Widget(QWidget *parent = nullptr);
~Widget();
protected:
virtual void paintEvent(QPaintEvent *event) override;
virtual void mouseMoveEvent(QMouseEvent *event) override;
virtual void mousePressEvent(QMouseEvent *event) override;
virtual void mouseReleaseEvent(QMouseEvent *event) override;
virtual void resizeEvent(QResizeEvent *event);
private:
void showMenu();
void hideMenu();
private:
Ui::Widget *ui;
bool mIsHoveringOnCloseButton;
bool mIsHoveringOnMenuButton;
bool mIsPressed;
QPointF mPressedPos;
QWidget* mMenu;
QPropertyAnimation * mMenuAnim;
};
#endif // WIDGET_H
CPP文件
#include "Widget.h"
#include "ui_Widget.h"
#include <QPaintEvent>
#include <QPainter>
#include <QDebug>
#include <QVBoxLayout>
#include <QLabel>
#define UpdateAccept \
{update();event->accept();return;}
Widget::Widget(QWidget *parent)
: QWidget(parent)
, ui(new Ui::Widget),mIsHoveringOnCloseButton(false),mIsPressed(false),mIsHoveringOnMenuButton(false)
{
ui->setupUi(this);
setWindowFlag(Qt::FramelessWindowHint);
setMouseTracking(true);
//init menu
mMenu = new QWidget(this);
mMenu->setStyleSheet("background:white;font-size:32px;");
QVBoxLayout * menuLayout = new QVBoxLayout;
menuLayout->addWidget(new QLabel("settings"));
menuLayout->addWidget(new QLabel("privacy"));
menuLayout->addWidget(new QLabel("profile"));
menuLayout->addWidget(new QLabel("collections"));
menuLayout->addStretch();
mMenu->setLayout(menuLayout);
//init menu animation
mMenuAnim = new QPropertyAnimation(mMenu,"pos");
}
void Widget::resizeEvent(QResizeEvent *event){
if(!event) return;
const auto size = event->size();
mMenu->setFixedWidth( size.width() /2.5);
mMenu->setFixedHeight(size.height());
mMenu->move(-size.width(),0);
}
void Widget::showMenu(){
mMenuAnim->setStartValue(QPoint( -mMenu->width() , 0));
mMenuAnim->setEndValue(QPoint(0,0));
mMenuAnim->setDuration(1000);
mMenuAnim->start();
}
void Widget::hideMenu(){
mMenuAnim->setEndValue(QPoint( -mMenu->width() , 0));
mMenuAnim->setStartValue(QPoint(0,0));
mMenuAnim->setDuration(1000);
mMenuAnim->start();
}
void Widget::mouseReleaseEvent(QMouseEvent *event){
mIsPressed = false;
QWidget::mouseReleaseEvent(event);
}
void Widget::mousePressEvent(QMouseEvent *event){
if(!event) return;
mIsPressed = true;
mPressedPos = event->pos();
if(mIsHoveringOnCloseButton){
this->close();
return;
}
if(mIsHoveringOnMenuButton){
showMenu();
event->accept();
return;
}
if(mMenu->pos().x() >= 0 && mMenuAnim->state() != QAbstractAnimation::Running){
hideMenu();
}
QWidget::mousePressEvent(event);
}
void Widget::mouseMoveEvent(QMouseEvent *event){
if(event){
if(mIsPressed){
auto pos = event->globalPos();
auto delta = pos - mPressedPos ;
this->move(delta.toPoint() );
event->accept();
return;
}
else{
auto pos = event->pos();
const auto x = pos.x();
const auto y = pos.y();
if(x >= this->width() - 32 && x <= this->width() &&
y >= 0 && y <= 32){
if(!mIsHoveringOnCloseButton){
mIsHoveringOnCloseButton = true;
UpdateAccept
}
}
else{
if(mIsHoveringOnCloseButton){
mIsHoveringOnCloseButton = false;
UpdateAccept
}
}
if(x >= 0 && x <= 32 && y >= 0 && y <= 32){
if(!mIsHoveringOnMenuButton){
mIsHoveringOnMenuButton = true;
UpdateAccept
}
}
else{
if(mIsHoveringOnMenuButton){
mIsHoveringOnMenuButton = false;
UpdateAccept
}
}
}
}
QWidget::mouseMoveEvent(event);
}
void Widget::paintEvent(QPaintEvent *event) {
if(event){
QPainter painter(this);
//draw title rectangle
auto titleRect = event->rect();
titleRect.setHeight(40);
painter.setBrush(QColor("darkgray"));
painter.setPen(Qt::NoPen);
painter.drawRect(titleRect);
//draw close button
auto closeButtonRect = event->rect();
closeButtonRect.setLeft(width() - 32);
closeButtonRect.setHeight(40);
QFont font;
font.setPixelSize(26);
painter.setFont(font);
if(mIsHoveringOnCloseButton)
painter.setPen(QColor("white"));
else
painter.setPen(QColor("black"));
painter.setBrush(Qt::NoBrush);
painter.drawText(closeButtonRect, "✘");
//draw menu
auto menuRect = event->rect();
menuRect.setLeft(10);
menuRect.setRight(40);
menuRect.setHeight(40);
if(mIsHoveringOnMenuButton)
painter.setPen(QColor("white"));
else
painter.setPen(QColor("black"));
painter.drawText(menuRect,"☰");
}
}
Widget::~Widget()
{
delete ui;
}