yurumi
20th August 2015, 22:54
Hi all,
I'm trying to generate mouse events using QGuiApplication::postEvent() and pass them to a QML scene. While the first event is processed correctly, following events are somehow stuck at the position of the first event. For example assume there are two MouseAreas left and right. When the first event is created inside the left MouseArea, onPressed() and onReleased() of this area are triggered. When the next event is created inside the right MouseArea, still the onPressed() and onReleased() of the left MouseArea are triggered. If I create an event with a real mouse the event occurs on the position of the last synthetic event. Anyhow, (solely) the next synthetic event is correct again. Also, after redrawing the window the next synthetic event is correct.
Besides postEvent() I tried sendEvent() and notify() in combination with flush(), sendPostedEvents() and sync() (although the events seem to be delivered - just at the wrong position). I also send the events to a receiver class derived from QObject with an overridden event() method: the coords of the events were correct.
Here is some sample code implementing the setup described above. Mouse events are generated alternating left and right every 3s. After a press event, a release event is created 0.3s later. If a MouseArea is pressed it turns green otherwise it is red. Real mouse events or moving the mouse over the rects cause the next synthetic event to be at the correct position.
mouseeventgenerator.h:
#ifndef MOUSEEVENTGENERATOR_H
#define MOUSEEVENTGENERATOR_H
#include <QtCore>
class QQuickView;
class MouseEventGenerator : public QObject
{
Q_OBJECT
public:
explicit MouseEventGenerator(QQuickView *viewer = 0);
public slots:
void generateMouseEvent();
void generateReleaseEventLeft();
void generateReleaseEventRight();
protected:
void postEvent(int x, int y, int gesture_code);
QQuickView* m_viewer;
QString m_lastSide;
};
#endif // MOUSEEVENTGENERATOR_H
mousegenerator.cpp:
#include "mouseeventgenerator.h"
#include <QtCore>
#include <QGuiApplication>
#include <QApplication>
#include <QtQuick/QQuickView>
MouseEventGenerator::MouseEventGenerator(QQuickVie w *viewer)
: QObject(),
m_viewer(viewer),
m_lastSide("")
{
QTimer *timer = new QTimer(this);
connect(timer, SIGNAL(timeout()), this, SLOT(generateMouseEvent()));
timer->start(3000);
}
void MouseEventGenerator::generateMouseEvent(){
if(m_lastSide == "right"){
postEvent(220, 220, 1);
QTimer::singleShot(300, this, SLOT(generateReleaseEventLeft()));
m_lastSide = "left";
}else{
postEvent(420, 220, 1);
QTimer::singleShot(300, this, SLOT(generateReleaseEventRight()));
m_lastSide = "right";
}
}
void MouseEventGenerator::generateReleaseEventLeft(){
postEvent(220, 220, 0);
}
void MouseEventGenerator::generateReleaseEventRight(){
postEvent(420, 220, 0);
}
void MouseEventGenerator::postEvent(int x, int y, int gesture_code){
if(gesture_code == 1){
QMouseEvent *pressEvent = new QMouseEvent(QEvent::MouseButtonPress, QPoint(x, y),
Qt::LeftButton, Qt::LeftButton, Qt::NoModifier);
QGuiApplication::postEvent(m_viewer, pressEvent);
}
else if(gesture_code == 0){
QMouseEvent *releaseEvent = new QMouseEvent(QEvent::MouseButtonRelease, QPoint(x,y),
Qt::LeftButton, Qt::LeftButton, Qt::NoModifier);
QGuiApplication::postEvent(m_viewer, releaseEvent);
}
}
main.qml:
import QtQuick 2.4
Item {
width: 640
height: 480
visible: true
Rectangle {
id: background
anchors.fill: parent
color: "black"
}
Rectangle {
id: rectLeft
x: 200
y: 200
width: 100; height: 100
color: "red"
MouseArea {
anchors.fill: parent
onPressed: {
parent.color = "green"
}
onReleased: {
parent.color = "red"
}
}
}
Rectangle {
id: rectRight
x: 400
y: 200
width: 100; height: 100
color: "red"
MouseArea {
anchors.fill: parent
onPressed: {
parent.color = "green"
}
onReleased: {
parent.color = "red"
}
}
}
}
main.cpp:
#include <QGuiApplication>
#include <QtQuick/QQuickView>
#include <QQmlContext>
#include "mouseeventgenerator.h"
int main(int argc, char *argv[])
{
QGuiApplication app(argc, argv);
QQuickView view;
MouseEventGenerator *generator = new MouseEventGenerator(&view);
view.setResizeMode(QQuickView::SizeRootObjectToVie w);
view.setSource(QUrl("qrc:/main.qml"));
view.show();
return app.exec();
}
Any help is highly appreciated!
Cheers,
Thomas
PS: I'm using Qt 5.4.2 and gcc 5.1.
PPS: Maybe this is somehow connected? [URL="http://http://www.qtcentre.org/threads/61989-Stop-mouse-event-and-start-on-another-widget"]
I'm trying to generate mouse events using QGuiApplication::postEvent() and pass them to a QML scene. While the first event is processed correctly, following events are somehow stuck at the position of the first event. For example assume there are two MouseAreas left and right. When the first event is created inside the left MouseArea, onPressed() and onReleased() of this area are triggered. When the next event is created inside the right MouseArea, still the onPressed() and onReleased() of the left MouseArea are triggered. If I create an event with a real mouse the event occurs on the position of the last synthetic event. Anyhow, (solely) the next synthetic event is correct again. Also, after redrawing the window the next synthetic event is correct.
Besides postEvent() I tried sendEvent() and notify() in combination with flush(), sendPostedEvents() and sync() (although the events seem to be delivered - just at the wrong position). I also send the events to a receiver class derived from QObject with an overridden event() method: the coords of the events were correct.
Here is some sample code implementing the setup described above. Mouse events are generated alternating left and right every 3s. After a press event, a release event is created 0.3s later. If a MouseArea is pressed it turns green otherwise it is red. Real mouse events or moving the mouse over the rects cause the next synthetic event to be at the correct position.
mouseeventgenerator.h:
#ifndef MOUSEEVENTGENERATOR_H
#define MOUSEEVENTGENERATOR_H
#include <QtCore>
class QQuickView;
class MouseEventGenerator : public QObject
{
Q_OBJECT
public:
explicit MouseEventGenerator(QQuickView *viewer = 0);
public slots:
void generateMouseEvent();
void generateReleaseEventLeft();
void generateReleaseEventRight();
protected:
void postEvent(int x, int y, int gesture_code);
QQuickView* m_viewer;
QString m_lastSide;
};
#endif // MOUSEEVENTGENERATOR_H
mousegenerator.cpp:
#include "mouseeventgenerator.h"
#include <QtCore>
#include <QGuiApplication>
#include <QApplication>
#include <QtQuick/QQuickView>
MouseEventGenerator::MouseEventGenerator(QQuickVie w *viewer)
: QObject(),
m_viewer(viewer),
m_lastSide("")
{
QTimer *timer = new QTimer(this);
connect(timer, SIGNAL(timeout()), this, SLOT(generateMouseEvent()));
timer->start(3000);
}
void MouseEventGenerator::generateMouseEvent(){
if(m_lastSide == "right"){
postEvent(220, 220, 1);
QTimer::singleShot(300, this, SLOT(generateReleaseEventLeft()));
m_lastSide = "left";
}else{
postEvent(420, 220, 1);
QTimer::singleShot(300, this, SLOT(generateReleaseEventRight()));
m_lastSide = "right";
}
}
void MouseEventGenerator::generateReleaseEventLeft(){
postEvent(220, 220, 0);
}
void MouseEventGenerator::generateReleaseEventRight(){
postEvent(420, 220, 0);
}
void MouseEventGenerator::postEvent(int x, int y, int gesture_code){
if(gesture_code == 1){
QMouseEvent *pressEvent = new QMouseEvent(QEvent::MouseButtonPress, QPoint(x, y),
Qt::LeftButton, Qt::LeftButton, Qt::NoModifier);
QGuiApplication::postEvent(m_viewer, pressEvent);
}
else if(gesture_code == 0){
QMouseEvent *releaseEvent = new QMouseEvent(QEvent::MouseButtonRelease, QPoint(x,y),
Qt::LeftButton, Qt::LeftButton, Qt::NoModifier);
QGuiApplication::postEvent(m_viewer, releaseEvent);
}
}
main.qml:
import QtQuick 2.4
Item {
width: 640
height: 480
visible: true
Rectangle {
id: background
anchors.fill: parent
color: "black"
}
Rectangle {
id: rectLeft
x: 200
y: 200
width: 100; height: 100
color: "red"
MouseArea {
anchors.fill: parent
onPressed: {
parent.color = "green"
}
onReleased: {
parent.color = "red"
}
}
}
Rectangle {
id: rectRight
x: 400
y: 200
width: 100; height: 100
color: "red"
MouseArea {
anchors.fill: parent
onPressed: {
parent.color = "green"
}
onReleased: {
parent.color = "red"
}
}
}
}
main.cpp:
#include <QGuiApplication>
#include <QtQuick/QQuickView>
#include <QQmlContext>
#include "mouseeventgenerator.h"
int main(int argc, char *argv[])
{
QGuiApplication app(argc, argv);
QQuickView view;
MouseEventGenerator *generator = new MouseEventGenerator(&view);
view.setResizeMode(QQuickView::SizeRootObjectToVie w);
view.setSource(QUrl("qrc:/main.qml"));
view.show();
return app.exec();
}
Any help is highly appreciated!
Cheers,
Thomas
PS: I'm using Qt 5.4.2 and gcc 5.1.
PPS: Maybe this is somehow connected? [URL="http://http://www.qtcentre.org/threads/61989-Stop-mouse-event-and-start-on-another-widget"]