Important: Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

Send QEvent to QGraphicsScene base on QGraphicsView rendering



  • Hi there!

    I'm trying to understanding how Qt send event to QGraphicsView.

    I create a QComboBox and my aim is to click on it using fake event. To do that I put my widget into a QGraphicsScene and my scene into a QGraphicsView. I render my view to see where the widget is and create my fake event base on this picture. On the picture the middle of combobox is at (320, 240). But if I send the event at this position, nothing happen. I should send the event near to (50, 5).

    My question is: How remove the margin of the scene?
    I try setSceneRect and it change nothing...

    The code:

    int main( int argc, char** argv) {
    	QApplication a(argc, argv);
    
    	QComboBox *comboBox = new QComboBox();
    	comboBox->addItem("test1");
    	comboBox->addItem("test2");
    	comboBox->addItem("test3");
    	comboBox->addItem("test4");
    
    	QGraphicsScene scene;
    	scene.addWidget(comboBox);
    	QGraphicsView view(&scene);
    
    	QImage image(view.size(), QImage::Format_RGBA8888);
    	image.fill(Qt::green);
    	QPainter painter(&image);
    	view.render(&painter);
    	image.save("view.png");
    
    	view.show();
    
    	Qt::MouseButtons buttons;
    	buttons |= Qt::LeftButton;
    	//QPointF mousePosF(50.f, 5.f);
    	QPointF mousePosF(320.f, 240.f);
    	QPoint mousePos = mousePosF.toPoint();
    
    	QGraphicsSceneMouseEvent* mouseEvent =
    		new QGraphicsSceneMouseEvent(QEvent::GraphicsSceneMousePress);
    	mouseEvent->setWidget(nullptr);
    	mouseEvent->setPos(mousePosF);
    	mouseEvent->setButtonDownPos(Qt::LeftButton, mousePosF);
    	mouseEvent->setButtonDownScenePos(Qt::LeftButton, mousePos);
    	mouseEvent->setButtonDownScreenPos(Qt::LeftButton, mousePos);
    	mouseEvent->setScenePos(mousePos);
    	mouseEvent->setScreenPos(mousePos);
    	mouseEvent->setLastPos(mousePosF);
    	mouseEvent->setLastScenePos(mousePos);
    	mouseEvent->setLastScreenPos(mousePos);
    	mouseEvent->setButtons(buttons);
    	mouseEvent->setButton(Qt::LeftButton);
    	mouseEvent->setModifiers(0);
    	mouseEvent->setAccepted(true);
    
    	QApplication::postEvent(&scene, mouseEvent);
    
    	return a.exec();
    }
    

    and the rendering:
    view.png

    Best regards!


  • Lifetime Qt Champion

    Hi,

    Can you explain what your end goal is ?



  • Hi,

    I'm trying to interact with offscreen widget using inputs recorded (It's a kind of QTest).
    I just find the function 'mapToScene' and that works well for most of widgets. If I well understand this issue (https://bugreports.qt.io/browse/QTBUG-47114?jql=project %3D QTBUG AND resolution %3D Unresolved AND text ~ "QGraphicsScene popup" ORDER BY updated DESC%2C priority DESC) is still open. So QMenu should not be use in this case I guess. Any workaround?

    Regards



  • If QTest::mouseClick and friends does not suit you for some reason, here is a code snippet that works for me:

    void CTcmg_TestHelpers::simulateMousePress(QWidget* const pWidget,
                                               const QPoint& widgetPos,
                                               const Qt::MouseButton pressedButton,
                                               const Qt::KeyboardModifiers& modifiers)
    {
        if (pWidget == nullptr)
        {
            return;
        }
    
        if (pressedButton == Qt::NoButton)
        {
            return;
        }
    
        QMouseEvent* pDown = createMouseEvent(pWidget, QEvent::MouseButtonPress,
                                              widgetPos, pressedButton,
                                              modifiers, pressedButton);
    
        notifyHelper(pWidget,
                     pDown);
        QApplication::processEvents();
    }
    
    QMouseEvent* CTcmg_TestHelpers::createMouseEvent(const QWidget* const pWidget,
                                                     const QEvent::Type eventType,
                                                     const QPoint& widgetPos,
                                                     const Qt::MouseButtons& buttons,
                                                     const Qt::KeyboardModifiers& modifiers,
                                                     Qt::MouseButton buttonCausingEvent,
                                                     bool bSpontaneous)
    {
        if (pWidget == nullptr)
        {
            return nullptr;
        }
    
    
        if (buttonCausingEvent == Qt::MouseButtonMask)
        {
            switch (eventType)
            {
                case QEvent::MouseButtonPress:
                case QEvent::MouseButtonRelease:
                case QEvent::MouseButtonDblClick:
                {
                    buttonCausingEvent = Qt::LeftButton;
                    break;
                }
                default:
                {
                    buttonCausingEvent = Qt::NoButton;
                    break;
                }
            }
        }
    
    
        QMouseEvent* pEvent = new QMouseEvent(eventType,
                                              widgetPos,
                                              pWidget->mapToGlobal(widgetPos),
                                              buttonCausingEvent,
                                              buttons,
                                              modifiers);
        if (bSpontaneous)
        {
            QSpontaneKeyEvent::setSpontaneous(pEvent);
        }
    
        return pEvent;
    }
    
    void CTcmg_TestHelpers::notifyHelper(QObject *pReceiver, QEvent *pEvent)
    {
        if (pEvent == nullptr)
        {
            return;
        }
    
        (void) getApplicationInstance()->notify(pReceiver,
                                                pEvent);
    }
    

    I hope it helps you to get going...

    EDIT: About your code: At the application level, Qt does not understand QGraphicsSceneXxxEvents. They are converted as the normal Event (e.g. MousePress) enter the QGraphicsView



  • Thx for the conversion!
    It works well now.

    Best regards!


Log in to reply