2012-10-18 44 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