2012-10-18 78 views
0

我使用Qt 4.8.3上X11。檢測的QMainWindow/QDialog的的移動端(QT 4.8)

我需要知道用戶什麼時候結束在屏幕上拖動一個窗口, 這是爲了讀取最終位置並最終開始動畫以將窗口位置調整爲「允許」的位置。

我注意到QWidget :: moveEvent是爲每個小動作調用的,但這是非常不方便的,因爲我必須在用戶釋放鼠標按鈕並且完全移動時執行位置檢查(並最終生成動畫)完了。

這是一個真正的問題:當用戶點擊標題欄時,似乎沒有辦法檢測到鼠標釋放事件(或獲取鼠標按鈕狀態),因爲它由操作系統控制,而不是Qt的。 我也嘗試過使用QWidget :: x11event(XEvent * e)...但事件僅在窗口內收集,而不是在標題欄中收集。

是否有人知道的方式來實現這一目標?

我懷疑,我將不得不重新實現標題欄自己...太糟糕了......

謝謝! ;-)

+0

您應該也可以考慮用戶使用鍵盤移動窗口的情況。 (至少在Windows中這是可能的,我不知道X11。) – 2012-10-18 14:55:50

+0

QMoveEvent每次移動時都會發布,無論移動的方式如何。但是,有QResizeEvent,這也可能影響窗口中的動畫。 – divanov

回答

0

讓我們看看下面的測試應用程序: 的main.cpp

#include <QApplication> 

#include "win.h" 

int main(int argc, char** argv) 
{ 
    QApplication app(argc, argv); 

    Win w; 
    w.show(); 

    return app.exec(); 
} 

win.h:

#include <QWidget> 
#include <QEvent> 
#include <QMoveEvent> 
#include <QDebug> 

class Win : public QWidget 
{ 
public: 
    Win(QWidget *parent = 0) : QWidget(parent) { 
     this->installEventFilter(this); 
    } 

protected: 
    bool eventFilter(QObject *obj, QEvent *event) { 
     if (event->type() == QEvent::Move) { 
      QMoveEvent *moveEvent = static_cast<QMoveEvent*>(event); 
      qDebug() << "Move event:" << moveEvent->pos(); 
     } else { 
      qDebug() << "Event type:" << event->type(); 
     } 
     return QWidget::eventFilter(obj, event); 
    } 
}; 

此應用程序只是安裝在本身並打印事件過濾器來安慰所有接收具有特殊格式的事件以便QMoveEvent在日誌中區分它。

典型日誌:

Event type: 203 
Event type: 75 
Move event: QPoint(0,0) 
Event type: 14 
Event type: 17 
Event type: 26 
Event type: 74 
Event type: 77 
Move event: QPoint(66,52) 
Event type: 12 
Event type: 24 
Event type: 99 
Event type: 77 
Event type: 12 
Event type: 10 
Event type: 11 
Move event: QPoint(308,356) 
Event type: 19 
Event type: 25 
Event type: 99 
Event type: 18 
Event type: 27 
Event type: 77 

正如你看到的,有2個移動事件,應用程序最初創建時,一個,當我完成窗口的動作。我正在用Qt 4.8.1和XOrg 7.6進行測試。

要查看原始X事件

  1. 有測試應用程序的運行。
  2. 獲取測試應用程序的窗口ID。爲此,請在命令行xwininfo -name WINDOW_NAME中執行,其中WINDOW_NAME是測試應用程序窗口的名稱。另一種選擇是使用不帶參數的xwininfo,然後你必須用鼠標指針選擇測試應用程序窗口。
  3. 運行X事件監視器xev -id 0x2a00002,其中0x2a00002是窗口ID在前面的步驟中發現。這將打印您的窗口從X服務器接收的X事件。 ConfigureNotify是與QMoveEvent對應的X協議。
+0

複製和粘貼代碼對我產生: '移動事件:QPoint(683135) Move事件:QPoint(682133) Move事件:QPoint(680131) Move事件:QPoint(679130) Move事件:QPoint (678128) 移動事件:QPoint(677128) 移動事件:QPoint(676128) 移動事件:QPoint(675128) 移動事件:QPoint(674128) 移動事件:QPoint(673128) 移動事件:QPoint(672128 ) 移動事件:QPoint(671,128) 移動事件:QPoint(670,128)' 每個增量移動得到通知.... Qt4 .8.3 XOrg 7.6 –

+0

有幾種可能導致這種情況的選項。你可以驗證X事件到你的應用程序,以確保它不是你的Qt版本問題。 – divanov

2

我有同樣的問題,因爲你的。 moveEvent在其移動的每個點都被觸發,而Qt沒有提供明確的方法來確定移動的結束。

但現在,通過divanov的回答啓發,我發現,當我們移動對話框後,鬆開鼠標,事件類型173總是被觸發。這是QEvent :: NonClientAreaMouseMove。

所以代碼很簡單。

首先安裝事件過濾器併發佈一個成員變量:int nLastEvent;

bool Win::eventFilter(QObject *obj, QEvent *event) 
{ 
    if (nLastEvent == QEvent::Move && event->type() == 173) 
    { 
     // do what you wanna do here when the mouse is released, 
     // like attaching the dialog to the main window 
    } 
    nLastEvent = event->type(); 
    return QWidget::eventFilter(obj, event); 
} 

它簡單而有效,不是嗎!

希望它對你也有用。 :)

+0

您的示例將無法在我的桌面上運行,從而使應用程序無法移植。正如你從我的日誌中可以看到的,沒有QEvent :: NonClientAreaMouseMove。你使用什麼樣的分配和窗口管理器? – divanov

+0

我使用的是Qt 4.8.3和Win7。在您的日誌中,釋放會自動檢測到。但這不是Matteo Murgida遇到的情況,儘管你擁有相同的開發環境。但是,我的問題是相似的,並得到解決。我只是提供一個不同的想法。 :-) – liulios

+0

如果是這樣,那麼我的答案幫助你解決你的問題。它值得投票嗎? – divanov