問題描述:
我們的自定義的Qt窗口,大多采用了隱藏框架、然後自定義窗口標題欄的方式,實現了窗口的定製。但是在測試、使用過程中,經常出現拖動非標題欄位置窗口也跟着移動、甚至跳動的現象。
解決方案:
重寫窗口部件的三個事件函數,mousePressEvent,mouseMoveEvent,mouseReleaseEvent。
在窗口類的內部定義一個記錄鼠標按下位置的QPoint m_mousePressPoint;默認值是一個y值大於窗口標題欄高度的點,可設置爲QPoint(0,100)。
在mousePressEvent事件中,判斷是否是左鍵按下,若是,則記錄鼠標按下的點,並獲取鼠標按下時所在位置的窗口部件,並對鼠標按下的點重新定位:若鼠標按下點所在的窗口部件是標題欄內部的窗口部件,則按下點保持不變,否則,將按下點置爲默認值。
在mouseMoveEvent事件中,通過按下點的位置與標題欄高度的對比,決定是否執行移動操作。若按下點的位置小於標題欄高度,則移動,否則不移動。(爲了避免由於標題欄的部件的邊界區域寬度較大時,造成拖動標題欄下邊緣無效的情況發生,要考慮標題欄窗口部件相對於其父窗口(this)的相對位置)
在mouseReleaseEvent事件中,將按下點恢復到默認值(因爲點擊combobox後,不觸發mousePressEvent,所以不會對按下點設置位置,而是保持上次的值,因此可能導致移動事件判斷出錯)。
參考代碼如下:
QPoint SubstationAlarmDlg::m_mousePressPoint;//定義記錄鼠標按下點。 void SubstationAlarmDlg::mousePressEvent(QMouseEvent* event) { if(event->button()==Qt::LeftButton)//判斷是否是左鍵點擊 { m_mousePressPoint = event->pos(); QWidget *tempWidget = childAt(m_mousePressPoint); if (tempWidget == ui.label_5 ||tempWidget == ui.titlelabel ||tempWidget == ui.closeBtn ||tempWidget == ui.label_2 ||tempWidget == ui.label_4 ||tempWidget == ui.label_6 ||tempWidget == ui.label ) //(不包含最大化、最小化、還原、關閉按鈕) { ;//判斷按下點所處的部件是否爲標題欄內的窗口部件,若是,不作爲。 } else { m_mousePressPoint = QPoint(0,100);//若不是,重置爲初始值。 } } } void SubstationAlarmDlg::mouseMoveEvent(QMouseEvent *event) { QPoint tempPoint = event->pos();//獲取事件發生位置 QRect selfRect = ui.logoWidget->geometry();//獲取窗口圖標相對於父窗體的矩形 int y = selfRect.y();//獲取矩形的高度 int tempHight = ui.logoWidget->height() + y;//獲取標題欄最下線到父窗體最上線的距離(作爲判斷對比值) if (m_mousePressPoint.y() < tempHight)//對比,確定是否移動。 { int tempX = tempPoint.x() - m_mousePressPoint.x(); int tempY = tempPoint.y() - m_mousePressPoint.y(); int nowX = this->x(); int nowY = this->y(); nowX += tempX; nowY += tempY; this->move(nowX, nowY); } } void SubstationAlarmDlg::mouseReleaseEvent(QMouseEvent *event) { m_mousePressPoint = QPoint(0, 100); }