Как имитировать перетаскивание с помощью QTest
Чтобы создать тестовый пример для ошибки перетаскивания в QTreeView
виджет Я попытался смоделировать поведение мыши при перетаскивании.
Я в основном выбираю первый элемент в QTreeView
и хотите перетащить его на третий элемент. Я сделал это, используя комбинациюQTest::mousePress
а также QTest::mouseMove
. В конце, конечно, должен бытьQTest::mouseRelease
, но мне уже не удалось воспроизвести mousePress и mouseMove.
Это шаги, необходимые для воспроизведения:
- Пользователь перемещает мышь в центр первого элемента
- Пользователь нажимает левую кнопку мыши
- Пользователь, удерживая левую кнопку мыши нажатой, перемещает мышь в центр третьего элемента.
- Пользователь отпускает левую кнопку мыши
Если выполнить эти действия, как описано, я вижу, что QTreeView
Виджеты реагируют соответствующим образом и указывают специальные выделения и вертикальные линии на случай, если элемент будет перемещаться между элементами.
К сожалению, мой автоматизированный тест не может воспроизвести это поведение. Кажется, что звонитQTest::mousePress
последовательно делает что-то другое. Также с помощью парыQTest::mousePress
а также QTest::mouseMove
это что-то другое.
Это мой код:
main.cpp
#include "TestObject.h"
#include <QTest>
QTEST_MAIN(TestObject)
TestObject.h
#include <QtTest/QtTest>
class TestObject : public QObject
{
Q_OBJECT
private slots:
void dragAndDrop();
};
TestObject.cpp
#include "TestObject.h"
#include "TestObject.moc"
#include <QTest>
#include <QTreeView>
#include <QStandardItemModel>
#include <QPropertyAnimation>
#include "MouseMover.h"
void TestObject::dragAndDrop() {
qDebug() << "Hello";
QStandardItemModel model;
QTreeView view;
view.setModel(&model);
view.show();
view.setHeaderHidden(true);
view.setDragDropMode(QAbstractItemView::DragDropMode::DragDrop);
view.setDefaultDropAction(Qt::DropAction::MoveAction);
view.setColumnHidden(1, true);
for (auto rowIter = 0; rowIter < 3; rowIter++) {
QList<QStandardItem*> items;
for (auto colIter = 0; colIter < 2; colIter++) {
items << new QStandardItem(QString("%1-%2").arg(rowIter).arg(colIter));
}
model.appendRow(items);
}
MouseMover mover;
mover.setWidget(view.viewport());
QPropertyAnimation anim(&mover, "mousePosition");
QTimer::singleShot(0, [&]() {
auto startValue = view.visualRect(model.index(0, 0)).center();
auto endValue = view.visualRect(model.index(2, 0)).center();
QTest::mousePress(view.viewport(), Qt::MouseButton::LeftButton, Qt::KeyboardModifier::NoModifier, startValue);
anim.setStartValue(startValue);
anim.setEndValue(endValue);
anim.setDuration(500);
anim.start();
});
qApp->exec();
}
MouseMover.h
#pragma once
#include <QObject>
#include <QTest>
class MouseMover : public QObject {
Q_OBJECT
public:
Q_PROPERTY(QPoint mousePosition READ mousePosition WRITE setMousePosition MEMBER mMousePosition)
void setWidget(QWidget* widget) {
mWidget = widget;
}
QPoint mousePosition() const {
return mMousePosition;
}
void setMousePosition(const QPoint& pos) {
mMousePosition = pos;
if (mWidget) {
QTest::mousePress(mWidget, Qt::MouseButton::LeftButton, Qt::KeyboardModifier::NoModifier, mMousePosition);
QTest::mouseMove(mWidget, mMousePosition);
}
}
private:
QPoint mMousePosition;
QWidget* mWidget{ nullptr };
};
MouseMover.cpp
#include "MouseMover.h"
1 ответ
mouseMoveEvent()
обработчик запускается и блокируется вQDrag.exec()
. Чтобы имитировать падение, вы должны запланировать его, например, с помощьюQTimer
:
def complete_qdrag_exec():
QTest.mouseMove(drop_target)
QTest.qWait(50)
QTest.mouseClick(drop_target, Qt.MouseButton.LeftButton)
QTimer.singleShot(1000, complete_qdrag_exec)
QTest.mousePress(drag_source, Qt.MouseButton.LeftButton, Qt.KeyboardModifier.NoModifier, QPoint(10, 10))
QTest.mouseMove(drag_source, QPoint(50, 50)) # Ensure distance sufficient for DND start threshold
Выше показан простой Python (PyQt6/PySide6). Я предполагаю, что это похоже на C++...