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

Pressing Child Widgets



  • Ok i have the following:

    A Class Minefield which has Cells as Childs.

    class Minefield : public QWidget
    {
        Q_OBJECT
    //....
    private:
        QVector<Cell *> mCells;
        CellInputHandler *mCellInputHandler;
    

    All Clicks etc get handled from CellInputHandler which is a child as well:

    // In Minefield Constructor:
    for(auto &cell : mCells) {
            cell->installEventFilter(mCellInputHandler);
        }
    

    Now i want to click on a Cell to test if a signal gets emitted. I have a test like this:

        QVector<Cell *> cells;
    
        cells << new Cell{ Cell::State::empty };
        cells << new Cell{ Cell::State::mine };
    
        cells << new Cell{ Cell::State::mine };
        cells << new Cell{ Cell::State::empty };
    
        constexpr auto height = 2;
        constexpr auto width = 2;
    
        auto cellWidth = cells[0]->width();
        auto cellHeight = cells[0]->height();
    
        Minefield obj{ cells, width, height };
    
        QSignalSpy spy(&obj, &Minefield::uncoveredFirstCell);
    
        QPoint pos = {obj.pos().x() + cellWidth/2,
                obj.pos().y() + cellHeight/2};
    
        auto child = obj.childAt(pos);  // I checked here that theres actually a child
    
        QTest::mousePress(&obj, Qt::LeftButton, Qt::NoModifier, pos);
        QTest::qWait(delayClickRightAndLeftTogether);
        QTest::mouseRelease(&obj, Qt::LeftButton, Qt::NoModifier, pos);
    
        QCOMPARE(spy.count(), 1);
    

    So theres a Cell at pos. But why i cannot click from the Parent like this:

        QTest::mousePress(&obj, Qt::LeftButton, Qt::NoModifier, pos);
        QTest::qWait(delayClickRightAndLeftTogether);
        QTest::mouseRelease(&obj, Qt::LeftButton, Qt::NoModifier, pos);
    

    I checked with the debugger any event code from the CellInputHandler is never hit.

    I already tested the Cellclass alone together with its CellInputHandler and could always click on a Cell like this.



  • I override for test mousePressEvent of Minefield:

    void Minefield::mousePressEvent(QMouseEvent *event)
    {
        QWidget::mousePressEvent(event);
    }
    

    I can see in the Debugger that it jumps into the mousePressEvent when I do the press the test.

    Then I would expect it would hit the installed Event filter CellInputHandler but it never happens:

    bool CellInputHandler::eventFilter(QObject *watched, QEvent *event)
    {
        if(event->type() == QEvent::MouseButtonPress){       
           handleMouseButtonPressEvents(watched, event);
           return true;
        }
        if(event->type() == QEvent::MouseButtonRelease){      
            handleMouseButtonReleaseEvents(watched, event);
           return true;
        }
        if(event->type() == QEvent::MouseMove) {
            handleMouseMoveEvents(event);
            return true;
        }
        return false;
    }
    

    So in short I expect the following:

    Clicking on Minefield at the pos were is a Cell.
    Minefield forwards the event to Cell. Since Cell has a event filter installed it should forward to it.

    But it does not happen. Why?


  • Lifetime Qt Champion

    @sandro4912 said in Pressing Child Widgets:

    QTest::mousePress

    hi
    It's only when using the QTest function the event filter is not triggered ?
    Meaning, actual real clicking on it work as expected ?

    My guess would be that QTest::mouseXXX synthesizes the corresponding Qt event directly and also send it directly to the widget you give as the parameter. However, i didnt check the source code if that is indeed the case.



  • @mrjj

    yes the application works if i run it as expected. i just wanted to add tests to verify. Maybe its a good idea to investigate the source code of the test framework for mouse press.



  • The Code for the mousepress can be found here:

    https://code.woboq.org/qt5/qtbase/src/testlib/qtestmouse.h.html

    It looks like they use a class QWindowSystemInterface to handle all the mouse events.

    Is there annother way to simulate a click on the widget?


Log in to reply