在qt中,如果設置的了窗口無邊框的話(即setWindowFlag(Qt::FramelessWindowHint);)那么窗口就沒法直接被鼠標拖動了,也沒法按住窗口的邊界進行縮放。
如果要實現縮放和拖動,一般來說就需要的重寫窗口類的mousePressEvent和mouseMoveEvent事件。
但是有些時候,比如在界面上放了一個QgraphicsView,主界面就沒法響應mousePressEvent和mouseMoveEvent事件。因為該事件被QgraphicsView截取了。這個時候我們就不能簡單得通過的重寫主窗口的鼠標事件來實現窗口的拖動和縮放了。
我是這樣實現的:
如下圖所示,我在界面上放了4個qlabel,通過qlabel的raise()方法將他們置頂,這樣,這些label就能獲取到鼠標移動和點擊事件了。
但是,我們是不能直接重寫qlabel中的鼠標事件響應函數的,因為在qlabel中,鼠標事件的級別是protected,如下圖:
所以這時候就需要我們自己寫一個類,繼承qlabel,代碼如下:
Mylabel.h
1 #ifndef MYLABEL_H 2 #define MYLABEL_H
3
4 #include <QObject>
5 #include <QLabel>
6 #include <QDebug>
7 #include <QMouseEvent>
8 #include <qnamespace.h>
9 class myLabel:public QLabel 10 { 11 Q_OBJECT 12 public: 13 myLabel(QWidget *parent=nullptr); 14 void setScaleCursor(int nshape = 0); 15 void mousePressEvent(QMouseEvent *ev); 16 void mouseMoveEvent(QMouseEvent *ev); 17 void mouseReleaseEvent(QMouseEvent *ev); 18 QPoint m_mousePointOld; 19 bool m_bKeepDrag; 20 signals: 21 void moveEventSig(QPoint point); 22 void mouseReleasedSig(); 23 }; 24
25 #endif // MYLABEL_H
Mylabel.cpp
1 #include "mylabel.h"
2
3 myLabel::myLabel(QWidget *parent):m_bKeepDrag(false) 4 { 5 this->setParent(parent); 6 } 7
8 void myLabel::setScaleCursor(int nshape) 9 { 10 if(nshape == 1)//左右拉伸
11 { 12 setCursor(Qt::SizeHorCursor); //改變光標形狀
13 } 14 else if(nshape == 2)//上下拉伸
15 { 16 setCursor(Qt::SizeVerCursor); 17 } 18 else if(nshape == 3)//右下拉伸
19 { 20 setCursor(Qt::SizeFDiagCursor); 21 } 22 else //正常顯示
23 { 24 setCursor(Qt::ArrowCursor); 25 } 26
27 } 28
29 void myLabel::mousePressEvent(QMouseEvent *ev) 30 { 31 if(ev->button() == Qt::LeftButton) 32 { 33 m_bKeepDrag = true; 34 m_mousePointOld = ev->globalPos(); 35 } 36 } 37
38 void myLabel::mouseMoveEvent(QMouseEvent *ev) 39 { 40 if(m_bKeepDrag) 41 { 42 const QPoint position = ev->globalPos() - m_mousePointOld; //the position of mainfrmae + (current_mouse_position - last_mouse_position) 43 //move(position.x(), position.y());
44 emit moveEventSig(position); 45 m_mousePointOld = ev->globalPos(); 46 } 47 } 48
49 void myLabel::mouseReleaseEvent(QMouseEvent *ev) 50 { 51 m_bKeepDrag = false; 52 emit mouseReleasedSig(); 53 }
在主界面的類中主要代碼如下:
頭文件里面定義這4個label
1 myLabel *labelLft; 2 myLabel *labelRit; 3 myLabel *labelBot; 4 myLabel *labelTop;
在cpp文件的構造函數中初始化這4個label,同時通過connect的方式建立信號槽,將label中的鼠標移動事件傳給主窗口,從而控制主窗口邊界的縮放
1 //上下左右的label,為了控制界面能夠拖動拉伸
2 labelLft = new myLabel(this); 3 labelLft->setStyleSheet("QLabel {background-color: transparent;}");//設置背景透明
4 labelLft->raise(); 5 labelLft->setScaleCursor(1); 6 connect(labelLft,&myLabel::moveEventSig,this,&MaxPicShowForm::getLeftScaleEvent); 7 labelRit = new myLabel(this); 8 labelRit->setStyleSheet("QLabel {background-color: transparent;}");//設置背景透明
9 labelRit->raise(); 10 labelRit->setScaleCursor(1);//設置為左右拉升光標
11 connect(labelRit,&myLabel::moveEventSig,this,&MaxPicShowForm::getRightScaleEvent); 12 labelBot = new myLabel(this); 13 labelBot->setStyleSheet("QLabel {background-color: transparent;}");//設置背景透明
14 labelBot->raise(); 15 labelBot->setScaleCursor(2);//設置為上下拉升光標
16 connect(labelBot,&myLabel::moveEventSig,this,&MaxPicShowForm::getBottomScaleEvent); 17 labelTop = new myLabel(this); 18 labelTop->setStyleSheet("QLabel {background-color: transparent;}");//設置背景透明
19 labelTop->setScaleCursor(2);//設置為上下拉升光標
20 connect(labelTop,&myLabel::moveEventSig,this,&MaxPicShowForm::getTopScaleEvent); 21 labelRB = new myLabel(this); 22 labelRB->setStyleSheet("QLabel {background-color: transparent;}");//設置背景透明
23 labelRB->setScaleCursor(3);//設置為右下拉升光標
24 connect(labelRB,&myLabel::moveEventSig,this,&MaxPicShowForm::getRBScaleEvent); 25 //設置4個label的位置:
26 labelLft->setGeometry(0,0,5,this->height()); 27 labelRit->setGeometry(this->width()-5,0,5,this->height()); 28 labelBot->setGeometry(0,this->height()-5,this->width(),5); 29 labelTop->setGeometry(0,0,this->width(),5);
響應鼠標拖動事件:
1 void MaxPicShowForm::getLeftScaleEvent(QPoint movPoint) 2 { 3 if((pos().x()+movPoint.x())>(pos().x()+this->width()-200)) 4 { 5 return;//保證拖動窗口左邊界的時候,控件寬度至少有200
6 } 7 this->setGeometry(pos().x()+movPoint.x(),pos().y(),this->width()-movPoint.x(),this->height()); 8 } 9
10 void MaxPicShowForm::getRightScaleEvent(QPoint movPoint) 11 { 12 if((pos().x()+this->width()+movPoint.x())<(pos().x()+200)) 13 { 14 return;//保證拖動窗口右邊界的時候,控件寬度至少有200
15 } 16 this->setGeometry(pos().x(),pos().y(),this->width()+movPoint.x(),this->height()); 17 } 18
19 void MaxPicShowForm::getBottomScaleEvent(QPoint movPoint) 20 { 21 if((pos().y()+this->height()+movPoint.y())<(pos().y()+200)) 22 { 23 return;//保證拖動窗口下邊界的時候,控件高度至少有200
24 } 25 this->setGeometry(pos().x(),pos().y(),this->width(),this->height()+movPoint.y()); 26 } 27
28 void MaxPicShowForm::getTopScaleEvent(QPoint movPoint) 29 { 30 if((pos().y()+movPoint.y())>(pos().y()+this->height()-200)) 31 { 32 return;//保證拖動窗口上邊界的時候,控件高度至少有200
33 } 34 this->setGeometry(pos().x(),pos().y()+movPoint.y(),this->width(),this->height()-movPoint.y()); 35 q}