Qt QGraphicsView unit testing - how to keep the mo

2019-06-18 19:47发布

问题:

I have a fairly complex QGraphicsView/Scene setup where by I have items with complex interactions.

As such I want to unit test this to avoid creating bugs in already existing functionality. For one test I wish to:

  1. Press the mouse down on an item in the scene
  2. Move the mouse to the right
  3. Release the mouse

This will allow me to check that the item was selected, was moved by the correct amount, and was deselected.

However I find that after sending mouseMove events the mouse state becomes "released", here is my code:

QTest.mousePress(gv.viewport(), Qt.LeftButton, Qt.NoModifier, QPoint(80,80), 100)
QTest.mouseMove(gv.viewport(), QPoint(80,80), 200)
QTest.mouseMove(gv.viewport(), QPoint(90,80), 300)
QTest.mouseMove(gv.viewport(), QPoint(100,80), 400)
QTest.mouseRelease(gv.viewport(), Qt.LeftButton, Qt.NoModifier, QPoint(80,80), 900)

Where gv is a QGraphicsView.

The problem seems to be that the mouseMove events are seen as hoverMoveEvents by the QGraphicsItem - it should be seen as a mouseMoveEvent!

According to the docs:

http://qt-project.org/doc/qt-4.8/qgraphicsitem.html#setAcceptHoverEvents

So it would seem that these simulated events do not set the "mouse grabber item"?

Related:

How to unit test qt graphics view widgets/items

Edit:

TLDR; Why are my fake mouse events not setting the current mouse grabber item? This causes QGraphicsItems to get mouseHover events instead of mouseMove events.

回答1:

Finally managed to get something that actually works:

w = gv.viewport()

# this actually gets the click to the view
#QTest.mouseMove(w, QPoint(80,80))
event = QMouseEvent(QEvent.MouseMove, QPoint(80,80), w.mapToGlobal(QPoint(80,80)), Qt.LeftButton, Qt.LeftButton, Qt.NoModifier);
#event.setSpontaneous(True)
QApplication.postEvent(w, event);
QTest.qWait(250)

#QTest.mouseMove(w, QPoint(80,80))
event = QMouseEvent(QEvent.MouseButtonPress, QPoint(80,80), w.mapToGlobal(QPoint(80,80)), Qt.LeftButton, Qt.LeftButton, Qt.NoModifier);
QApplication.postEvent(w, event);
QTest.qWait(250)

count = 0
while count < 20:

    #QTest.mouseMove(w, QPoint(80+count,80+count))
    event = QMouseEvent(QEvent.MouseMove, QPoint(80+count,80+count), w.mapToGlobal(QPoint(80+count,80+count)), Qt.LeftButton, Qt.LeftButton, Qt.NoModifier);
    QApplication.postEvent(w, event);
    t = w.mapToGlobal(QPoint(80+count,80+count))
    #QCursor.setPos(t)
    QTest.qWait(20)
    count = count + 1

event = QMouseEvent(QEvent.MouseButtonRelease, QPoint(100,100), w.mapToGlobal(QPoint(100,100)), Qt.LeftButton, Qt.LeftButton, Qt.NoModifier);
QApplication.postEvent(w, event);

Why these fabricated events work and the QTest ones don't I have no idea..

It appears that QTest will physically move the mouse, where as this code acts as if the mouse had moved but hasn't. Confusing I know!