从CSDN过来的兄弟们有福了,调了2天无私奉献,CPP一共130行,看还有精简的地方吗?
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include <QRubberBand>
QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
QT_END_NAMESPACE
#define DEFAULT_CURSOR Qt::ArrowCursor
class MainWindow : public QMainWindow
{
Q_OBJECT
Q_PROPERTY(int m_borderWidth READ borderWidth WRITE setBorderWidth)
Q_PROPERTY(bool m_dragEnable READ dragEnable WRITE setDragEnable)
Q_PROPERTY(bool m_bottomRightResizeEnable READ bottomRightResizeEnable WRITE setBottomRightResizeEnable)
public:
MainWindow(QWidget *parent = nullptr);
~MainWindow();
enum Edge {
None = 0x0,
Left = 0x1,
Top = 0x2,
Right = 0x4,
Bottom = 0x8,
TopLeft = Top|Left,
TopRight = Top|Right,
BottomLeft = Bottom|Left,
BottomRight = Bottom|Right,
};
Q_DECLARE_FLAGS(Edges, Edge)
protected:
bool eventFilter(QObject *o, QEvent *e) override;
void leaveEvent(QEvent *event);
void mousePressEvent(QMouseEvent*e);
void hoverMoveEvent(QHoverEvent*);
void mouseReleaseEvent(QMouseEvent*);
private:
Qt::CursorShape calculateCursorPosition(const QPoint &, const QRect &, Edges &);
void setBorderWidth(int w) {m_borderWidth = w;}
int borderWidth() const {return m_borderWidth;}
void setDragEnable(bool w) {m_dragEnable = w;}
bool dragEnable() const {return m_dragEnable;}
void setBottomRightResizeEnable(bool w) {m_bottomRightResizeEnable = w;}
bool bottomRightResizeEnable() const {return m_bottomRightResizeEnable;}
private slots:
void on_pushButton_clicked();
void on_pushButton_2_clicked();
void on_pushButton_3_clicked();
private:
Ui::MainWindow *ui;
QRect m_startRect;
bool m_leftButtonPressed;
Edges m_edgeOnMousePress = Edge::None;
int m_borderWidth = 6;
QPoint m_dragPos;
bool m_dragStart = false,m_dragEnable = true;
bool m_bottomRightResizeEnable = true;
};
#endif // MAINWINDOW_HCPP:
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QMouseEvent>
#include <QTimer>
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::MainWindow),
m_leftButtonPressed(false),
m_dragPos(QPoint())
{
ui->setupUi(this);
setWindowFlag(Qt::FramelessWindowHint);
installEventFilter(this);
}
MainWindow::~MainWindow()
{
delete ui;
}
bool MainWindow::eventFilter(QObject *o, QEvent *e)
{
if (e->type()==QEvent::HoverMove && o==this) {
hoverMoveEvent(static_cast<QHoverEvent*>(e));
return true;
}
return QMainWindow::eventFilter(o, e);
}
void MainWindow::leaveEvent(QEvent *event)
{
Q_UNUSED(event);
if (!m_leftButtonPressed)
unsetCursor();
}
void MainWindow::mousePressEvent(QMouseEvent *e)
{
if (e->button() & Qt::LeftButton) {
m_leftButtonPressed = true;
if (calculateCursorPosition(e->globalPos(), geometry(), m_edgeOnMousePress) != DEFAULT_CURSOR)
m_startRect = geometry();
if (this->rect().marginsRemoved(QMargins(borderWidth(), borderWidth(), borderWidth(), borderWidth())).contains(e->pos())) {
m_dragStart = true;
m_dragPos = e->pos();
}
}
}
void MainWindow::mouseReleaseEvent(QMouseEvent *e)
{
if (e->button() & Qt::LeftButton) {
m_leftButtonPressed = false;
m_dragStart = false;
if(!m_edgeOnMousePress.testFlag(Edge::None))
unsetCursor();
}
}
void MainWindow::hoverMoveEvent(QHoverEvent *e)
{
Edges currentEdge = Edge::None;
static bool _cursorchanged = false;
if (this->isFullScreen() || this->isMaximized()) {
// 一般不来这里,除非拖拉同时按快捷键最大化
if (_cursorchanged){
unsetCursor();
_cursorchanged = false;
}
return;
}
if(!m_leftButtonPressed){
auto shape = calculateCursorPosition(mapToGlobal( e->pos() ), geometry(), currentEdge);
if (!currentEdge.testFlag(Edge::None)){
setCursor(shape);
_cursorchanged = true;
}else if (_cursorchanged) {
unsetCursor();
_cursorchanged = false;
}
}else{
if (m_dragStart) {
move(geometry().topLeft() + (e->pos() - m_dragPos));
}else if (!m_edgeOnMousePress.testFlag(Edge::None)) {
auto curPos = mapToGlobal( e->pos() );
if(m_edgeOnMousePress&(Edge::Top))
m_startRect.setTop(curPos.y());
if(m_edgeOnMousePress&(Edge::Bottom))
m_startRect.setBottom(curPos.y());
if(m_edgeOnMousePress&(Edge::Left))
m_startRect.setLeft(curPos.x());
if(m_edgeOnMousePress&(Edge::Right))
m_startRect.setRight(curPos.x());
QTimer::singleShot(0,this,[=](){
setGeometry(m_startRect);
});
}
}
}
#define EDGE_RET2(rect,pos,out,edg,cursor) do{if(rect.contains(pos,true)){out=edg;return cursor;}}while(0)
Qt::CursorShape MainWindow::calculateCursorPosition(const QPoint &pos, const QRect &framerect, Edges &_edge)
{
QRect recL(framerect.x(),framerect.y()+m_borderWidth,m_borderWidth,framerect.height()-2*m_borderWidth);
EDGE_RET2(recL,pos,_edge,Edge::Left,Qt::SizeHorCursor);
QRect recR(framerect.right()-m_borderWidth,framerect.y()+m_borderWidth,m_borderWidth,framerect.height()-2*m_borderWidth);
EDGE_RET2(recR,pos,_edge,Edge::Right,Qt::SizeHorCursor);
QRect recB(framerect.x()+m_borderWidth,framerect.bottom()-m_borderWidth,framerect.width() - 2*m_borderWidth,m_borderWidth);
EDGE_RET2(recB,pos,_edge,Edge::Bottom,Qt::SizeVerCursor);
QRect recT(framerect.x()+m_borderWidth,framerect.y(),framerect.width() - 2*m_borderWidth,m_borderWidth);
EDGE_RET2(recT,pos,_edge,Edge::Top,Qt::SizeVerCursor);
QRect recBL(framerect.x(),framerect.bottom()-m_borderWidth,m_borderWidth,m_borderWidth);
EDGE_RET2(recBL,pos,_edge,Edge::BottomLeft,Qt::SizeBDiagCursor);
if(m_bottomRightResizeEnable){
QRect recBR(framerect.right()-m_borderWidth,framerect.bottom()-m_borderWidth,m_borderWidth,m_borderWidth);
EDGE_RET2(recBR,pos,_edge,Edge::BottomRight,Qt::SizeFDiagCursor);
}
QRect recTR(framerect.right()-m_borderWidth,framerect.y(),m_borderWidth,m_borderWidth);
EDGE_RET2(recTR,pos,_edge,Edge::TopRight,Qt::SizeBDiagCursor);
QRect recTL(framerect.x(),framerect.y(),m_borderWidth,m_borderWidth);
EDGE_RET2(recTL,pos,_edge,Edge::TopLeft,Qt::SizeFDiagCursor);
_edge = Edge::None;
return DEFAULT_CURSOR;
}
void MainWindow::on_pushButton_clicked()
{
resize(400,300);
}
void MainWindow::on_pushButton_2_clicked()
{
static bool isMax = true;
if(isMax)
showMaximized();
else
showNormal();
isMax = !isMax;
}
void MainWindow::on_pushButton_3_clicked()
{
close();
}实现是实现了,不过呢,用原生的resize / move / setGeometry 函数频繁了会导致边缘抖动,这个应该是QT内部没有做好。
要解决这个问题,有2个方法,请看下篇文章。