检测QMainWindow/QDialog(Qt 4.8)移动结束
我在X11上使用Qt4.8.3 我需要知道当用户在屏幕上拖动窗口时, 这是为了读取最终位置并最终启动动画以将窗口位置调整为“允许”位置 我注意到,每个小动作都会调用检测QMainWindow/QDialog(Qt 4.8)移动结束,qt,qt4,qdialog,qmainwindow,qt4.8,Qt,Qt4,Qdialog,Qmainwindow,Qt4.8,我在X11上使用Qt4.8.3 我需要知道当用户在屏幕上拖动窗口时, 这是为了读取最终位置并最终启动动画以将窗口位置调整为“允许”位置 我注意到,每个小动作都会调用QWidget::moveEvent,但这非常不方便,因为只有当用户释放鼠标按钮并且动作完全完成时,我才能执行位置检查(并最终启动动画) 这是真正的问题:当用户单击标题栏时,似乎没有办法检测鼠标释放事件(或获取鼠标按钮状态),因为它是由操作系统控制的,而不是由Qt控制的。 我还尝试了QWidget::x11event(XEvent*e
QWidget::moveEvent
,但这非常不方便,因为只有当用户释放鼠标按钮并且动作完全完成时,我才能执行位置检查(并最终启动动画)
这是真正的问题:当用户单击标题栏时,似乎没有办法检测鼠标释放事件(或获取鼠标按钮状态),因为它是由操作系统控制的,而不是由Qt控制的。
我还尝试了QWidget::x11event(XEvent*e)
…但是事件只在窗口中收集,而不是在标题栏中收集
有人知道实现这一目标的方法吗
<>我怀疑我自己必须重新实施标题栏…太糟糕了… 让我们考虑下面的测试应用: main.cpp 如您所见,有两个移动事件,一个是在应用程序最初创建时,另一个是在我完成窗口移动后。我用Qt4.8.1和XOrg 7.6进行测试 检查原始X事件的步骤
xwininfo-name WINDOW\u name
中执行,其中WINDOW\u name
是测试应用程序窗口的名称。另一个选项是使用不带参数的xwininfo,然后必须用鼠标指针选择测试应用程序窗口xev-id 0x2a00002
,其中0x2a00002
是在上一步中找到的窗口id。这将打印窗口从X服务器接收的X事件ConfigureNotify
是QMoveEvent
的X协议对应项让我们考虑下面的测试应用: main.cpp
如您所见,有两个移动事件,一个是在应用程序最初创建时,另一个是在我完成窗口移动后。我用Qt4.8.1和XOrg 7.6进行测试 检查原始X事件的步骤xwininfo-name WINDOW\u name
中执行,其中WINDOW\u name
是测试应用程序窗口的名称。另一个选项是使用不带参数的xwininfo,然后必须用鼠标指针选择测试应用程序窗口xev-id 0x2a00002
,其中0x2a00002
是在上一步中找到的窗口id。这将打印窗口从X服务器接收的X事件ConfigureNotify
是QMoveEvent
的X协议对应项我和你有同样的问题。moveEvent在移动过程中的每个点都会触发,而Qt没有提供明确的方法来确定移动的结束 但是现在,受divanov回答的启发,我发现当我们移动对话框后释放鼠标时,总是会触发键入173的事件。这就是QEvent::NonClienteamouseMove 所以代码很简单 首先安装事件过滤器并宣布一个成员变量:
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);
}
这很简单也很有效,不是吗
希望它对您也有用。:) 我和你有同样的问题。moveEvent在移动过程中的每个点都会触发,而Qt没有提供明确的方法来确定移动的结束
但是现在,受divanov回答的启发,我发现当我们移动对话框后释放鼠标时,总是会触发键入173的事件。这就是QEvent::NonClienteamouseMove
所以代码很简单
首先安装事件过滤器并宣布一个成员变量: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);
}
这很简单也很有效,不是吗
希望它对您也有用。:) 意识到这是一个非常古老的问题,这是您尝试“Qt检测窗口移动事件的结束”时遇到的第一个问题。因此,我想我应该添加一个解决方案,该解决方案与当前(撰写本文时)的Qt版本5.12.3配合得很好
您可以设置一个小型状态机,该状态机提供边界,以便使用QObject::eventFilter()
知道顶级窗口的位置何时被更改。在Qt 5.12.x中,当鼠标在窗口的非客户端区域(例如标题栏)中按下时,您将收到一个QEvent::nonclientreamousebutonpress
事件,当窗口位置发生变化(如果有)时,将收到一个后续的QEvent::Move
事件,然后在释放鼠标按钮时出现最后一个QEvent::nonclientreamousebutonrelease
事件
知道这个序列,并使用一个持久的布尔状态标志(user\u moved\u window
)来知道实际更改的位置,将在QObject::eventFilter()方法中为您提供以下代码片段:
bool MainWindow::eventFilter(QObject *obj, QEvent *event)
{
QEvent::Type event_type = event->type();
[...]
else if(event_type == QEvent::NonClientAreaMouseButtonPress)
user_moved_window = false;
else if(event_type == QEvent::Move && isVisible())
user_moved_window = true;
else if(event_type == QEvent::NonClientAreaMouseButtonRelease)
{
if(user_moved_window)
{
// do what you need to do to here to respond to
// the end of the reposition event...
user_moved_window = false;
}
}
[...]
return MainWindow::eventFilter(obj, event);
}
根据您的情况,您可能需要添加一些额外的检查——例如,确保事件的obj
实际上是主窗口——但是这个示例对于使用Qt 5.12.3的我的生产代码非常有效。意识到这是一个非常老的问题,这是您尝试时遇到的第一个问题“Qt检测窗口移动事件的结束”。因此,我想我应该添加一个解决方案,该解决方案与当前(截至本文撰写之时)的Qt版本5.12.3配合良好
您可以使用QObject::eventFilter()
设置一个小型状态机,该状态机提供边界,以便知道顶级窗口的位置何时被更改。在Qt 5.12.x中,当鼠标在窗口的非客户端区域按下时,您将收到一个QEvent::nonclientareamousebutonpress
事件(例如标题栏),子标题
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);
}
bool MainWindow::eventFilter(QObject *obj, QEvent *event)
{
QEvent::Type event_type = event->type();
[...]
else if(event_type == QEvent::NonClientAreaMouseButtonPress)
user_moved_window = false;
else if(event_type == QEvent::Move && isVisible())
user_moved_window = true;
else if(event_type == QEvent::NonClientAreaMouseButtonRelease)
{
if(user_moved_window)
{
// do what you need to do to here to respond to
// the end of the reposition event...
user_moved_window = false;
}
}
[...]
return MainWindow::eventFilter(obj, event);
}