移動無邊框表單的代碼網上很多,其原理都是一樣的,但是是有問題的,我這裡只是對其修正一下
網上的代碼僅僅實現了兩個事件
void EditDialog::mousePressEvent(QMouseEvent *event){ if (event->button() == Qt::LeftButton) { m_DragPosition = event->globalPos() - this->pos(); event->accept(); }}void EditDialog::mouseMoveEvent(QMouseEvent *event){ if (event->buttons() && Qt::LeftButton) { move(event->globalPos() - m_DragPosition); event->accept(); }}
但是這樣就會有一個問題,就是當滑鼠在一個實現了mousePressEvent的類上點擊時(比如QPushButton)會被該類優先處理此事件
而不會將事件傳遞到表單的mousePressEvent中。繼續,當移動滑鼠到這個按鈕外時(假設點在了QPushButton上)會觸發表單的mouseMoveEvent
從而導致計算座標時發生錯誤,此時你就會看到表單閃了一下,變動了位置,滑鼠也沒有停在前面按下的按鈕之上。
解決辦法也很簡單,就是再多聲明一個bool變數來判斷,並實現mouseReleaseEvent即可
void EditDialog::mousePressEvent(QMouseEvent *event){ if (event->button() == Qt::LeftButton) { m_Drag = true; m_DragPosition = event->globalPos() - this->pos(); event->accept(); }}void EditDialog::mouseMoveEvent(QMouseEvent *event){ if (m_Drag && (event->buttons() && Qt::LeftButton)) { move(event->globalPos() - m_DragPosition); event->accept(); }}void EditDialog::mouseReleaseEvent(QMouseEvent *){ m_Drag = false;}
這樣,就完成了無邊框表單的拖動。可是,這樣做的效率並不高,因為滑鼠每次move時都會觸發事件,計算位置,移動視窗,重繪視窗……
當表單上有QWebView組件時,特別是網頁中有圖片,Flash時,你就會發現用上面的方案去移動表單時會非常不流暢。
如果不考慮跨平台,只針對Windows平台,那麼我建議用Windows下的標準方法,類比標題列移動訊息,既簡單又高效
void MainWindow::mousePressEvent(QMouseEvent *event){ if (ReleaseCapture()) SendMessage(HWND(this->winId()), WM_SYSCOMMAND, SC_MOVE + HTCAPTION, 0); event->ignore();}
這樣,在拖動表單時只會在鬆開滑鼠時才將表單移動過去,這樣就避免了第一種方法的低效率問題