QMouseEvent的行为与正常的鼠标单击不同



我目前正在用几年前编写的触摸屏驱动程序来解决几个错误,该驱动程序用于支持该应用程序中的触摸屏,该应用程序运行在不支持本机触摸屏的操作系统上。我的驱动程序只需直接从/dev/input中的设备读取事件,并生成QMouseEvents来模拟触摸屏功能。如果重要的话,最初的操作系统是Scientific Linux 6.4,我们目前正在RedHat 8.4上运行它。

从那以后,我们转向了一种支持触摸屏的较新操作系统,但除非迫不得已,否则我们不想重写我们的应用程序来使用本机触摸驱动程序,因为这是一项劳民伤财的工作。所以我只是禁用了原生触摸驱动程序,这样它就不会在我的驱动程序生成的内容之外生成额外的触摸事件。然而,有一个特殊的行为困扰着我。

我们的应用程序中有一个滑块,其顶部/底部有+/-按钮,用于按单个刻度递增。当你用鼠标点击这些时,它只会向上或向下移动1个刻度。然而,如果你用触摸屏点击它,它会增加,然后迅速向上或向下滑动到另一端,就像你按住鼠标按下按钮一样。

我已经用日志文件验证了QEvent::MouseButtonPressQEvent::MouseButtonRelease事件都是生成的,并且针对同一位置的同一个小部件。

QT对QMouseEvent的处理方式是否与本机系统鼠标事件不同?或者这种行为还有其他解释吗?以下是我如何生成和调度事件的示例:

void InputHandler::touchPress(TouchPoint * tp, QWidget * widget) {
QPoint screenPos(tp->cx(), tp->cy());
QWidget * target = widget;
if(target == NULL) target = QApplication::widgetAt(screenPos);
if(target != NULL) {
QPoint local = target->mapFromGlobal(screenPos);
QMouseEvent * press = new QMouseEvent(QEvent::MouseButtonPress, local, screenPos, Qt::LeftButton, Qt::LeftButton, Qt::NoModifier);
QApplication::postEvent(target, press);
DBG(" -- touch press on: " << typeid(*widget).name());
// Check to see if the target is a QLineEdit or QComboBox, and if so, set focus on it.
QLineEdit * lineEdit = dynamic_cast<QLineEdit*>(target);
QComboBox * comboBox = dynamic_cast<QComboBox*>(target);
if(lineEdit) lineEdit->setFocus(Qt::MouseFocusReason);
if(comboBox) comboBox->setFocus(Qt::MouseFocusReason);
}
}

然后touchRelease方法也是一样的,但没有焦点线,而是使用`QEvent::MouseButtonReleaseinstead ofQEvent::MouseButton Press``。我从函数头识别目标小部件的方式是一个助手函数,它将点击位置的小部件动态投射到触摸功能中涉及的各种小部件,如果投射的对象不为空,我知道它是什么小部件,以及调用哪个触摸功能。

有什么想法吗?

编辑:好的,所以通过将方法修改为使用QApplication::sendEvent()而不是QApplication::postEvent()来解决问题。但现在有一个问题,尽管我的图像处理方法有效,但当我点击按钮时,应用程序会冻结或因分割故障而崩溃,GDB显示以下错误:

QWidget::repaint: Recursive repaint detected
QBackingStore::endPaint() called with an active painter; did you forget to destroy it or call QPainter::end() on it?

听起来你的paintEvent除了画画之外还做其他事情。比如称之为touchPress,而您的mousePressEvent直接或间接地执行repaint()

当你使用postEvent时,这个无限触发的鼠标按下循环会经过事件循环,你会得到重复点击的效果。当你使用sendEvent时,有一个不经过事件循环的直接调用,你会得到你说的错误(如果Qt-paint代码没有检查,你会从无界递归中得到堆栈溢出(。

解决方案是确保您的paintEvent不会直接触发任何其他事件。如果没有看到所有相关的代码,很难说你应该做什么。如果你运气好的话,解决办法就是做";什么都没有";,这意味着你现在在某个地方有一些额外的呼叫/事件,你只需要找到它并将其删除。

最新更新