如何在QTest中生成鼠标点击QGraphicsWidget?

How to generate mouse click on QGraphicsWidget in QTest?

我想测试在我的面板上按下按钮的功能。 问题是按钮不是 QPushButtons,而是 QGraphicWidget 元素。

如何生成此按钮鼠标单击以测试其行为?

按钮不是简单的 QPushButtons,因为它们在鼠标悬停时有特殊的行为,是动画的等等。 这些按钮被添加到场景中,然后场景被添加到视图中,视图作为一个小部件被添加到布局中。 我可以看到可以使用以下方式单击视图:

QTest.mouseClick(self.panel_with_buttons.view.viewport(), Qt.LeftButton)

但这并没有点击按钮。 我也试过指定按钮的位置:

rect = self.panel_with_buttons.button2.boundingRect()
QTest.mouseClick(self.panel_with_buttons.view.viewport(), Qt.LeftButton, pos = rect.center())

但由于某些原因,这是不受支持的论点

按钮代码 class 和 PanelWithButtons class (panel_with_buttons.py):

from PySide2 import QtWidgets, QtCore, QtGui


class Button(QtWidgets.QGraphicsWidget):
    pressed = QtCore.Signal()

    def __init__(self, image_path: str, parent=None):
        super().__init__(parent)
        self._pixmap = QtGui.QPixmap(image_path)

    def paint(self, painter, option, widget=None):
        painter.setPen(QtCore.Qt.NoPen)
        painter.drawPixmap(0, 0, self._pixmap)

    def mousePressEvent(self, event: QtWidgets.QGraphicsSceneMouseEvent):
        self.pressed.emit()


class PanelWithButtons(QtWidgets.QWidget):
    def __init__(self, parent=None):
        super().__init__(parent)

        self.button = QtWidgets.QPushButton('button1')
        self.button.clicked.connect(self.button_clicked)

        pix = 'home.png'
        self.button2 = Button(pix)
        self.button2.pressed.connect(self.button2_pressed)

        layout = QtWidgets.QVBoxLayout()
        layout.addWidget(self.button)
        self.scene = QtWidgets.QGraphicsScene()
        self.scene.addItem(self.button2)
        self.view = QtWidgets.QGraphicsView(self.scene)
        layout.addWidget(self.view)

        self.setLayout(layout)

    @QtCore.Slot()
    def button_clicked(self):
        print('button1 clicked')

    @QtCore.Slot()
    def button2_pressed(self):
        print('button2 pressed')

test.py:

from unittest import TestCase
from PySide2 import QtWidgets
from PySide2.QtTest import QTest
from PySide2.QtCore import Qt, QPoint
from test.panel_with_buttons import PanelWithButtons


class TestPanel(TestCase):
    def setUp(self) -> None:
        app = QtWidgets.QApplication()
        self.panel_with_buttons = PanelWithButtons()

    def test_go_cargo(self):
        QTest.mouseClick(self.panel_with_buttons.button, Qt.LeftButton)
        rect = self.panel_with_buttons.button2.boundingRect()
        QTest.mouseClick(self.panel_with_buttons.view.viewport(), Qt.LeftButton)

作为输出,我收到了对第一个按钮的鼠标点击(我可以看到 'button1 clicked'),但我不知道如何生成对第二个按钮的点击。

panel_with_buttons.py 文件有以下错误:

  • 您必须创建资源的绝对路径,在本例中为图像路径。当你 运行 一个 .py 文件时,如果传递了相对路径,这将是启动脚本的位置,这可能会带来问题,假设图像在 panel_with_buttons.py.

    [= 旁边25=]
  • 您必须使用 resize() 方法将 Button 的大小设置为图像的大小。

考虑到文件应该是这样的:

import os
from PySide2 import QtWidgets, QtCore, QtGui

current_dir = os.path.dirname(os.path.realpath(__file__))


class Button(QtWidgets.QGraphicsWidget):
    pressed = QtCore.Signal()

    def __init__(self, image_path: str, parent=None):
        super().__init__(parent)
        self._pixmap = QtGui.QPixmap(image_path)
        self.resize(self._pixmap.size())

    def paint(self, painter, option, widget=None):
        painter.setPen(QtCore.Qt.NoPen)
        painter.drawPixmap(0, 0, self._pixmap)

    def mousePressEvent(self, event: QtWidgets.QGraphicsSceneMouseEvent):
        self.pressed.emit()
        super().mousePressEvent(event)


class PanelWithButtons(QtWidgets.QWidget):
    def __init__(self, parent=None):
        super().__init__(parent)

        self.button = QtWidgets.QPushButton("button1")
        self.button.clicked.connect(self.button_clicked)

        print(os.getcwd())
        pix = os.path.join(current_dir, "home.png")
        self.button2 = Button(pix)
        self.button2.pressed.connect(self.button2_pressed)

        layout = QtWidgets.QVBoxLayout()
        layout.addWidget(self.button)
        self.scene = QtWidgets.QGraphicsScene()
        self.scene.addItem(self.button2)
        self.view = QtWidgets.QGraphicsView(self.scene)
        layout.addWidget(self.view)

        self.setLayout(layout)

    @QtCore.Slot()
    def button_clicked(self):
        print("button1 clicked")

    @QtCore.Slot()
    def button2_pressed(self):
        print("button2 pressed")


if __name__ == "__main__":
    import sys

    app = QtWidgets.QApplication(sys.argv)
    w = PanelWithButtons()
    w.show()
    sys.exit(app.exec_())

另一方面,您必须使用 Button 的 mapToScene 方法和 QGraphicsView 的 mapFromScene 方法获取属于 Button 的点相对于视口的位置,在这种情况下,该点将是 Button 的中心。

from unittest import TestCase
from PySide2 import QtCore, QtCore, QtWidgets, QtTest

from test.panel_with_buttons import PanelWithButtons


class TestPanel(TestCase):
    def setUp(self) -> None:
        app = QtWidgets.QApplication()
        self.panel_with_buttons = PanelWithButtons()
        self.panel_with_buttons.resize(640, 480)

    def test_go_cargo(self):
        QtTest.QTest.mouseClick(
            self.panel_with_buttons.button, QtCore.Qt.LeftButton
        )
        it = self.panel_with_buttons.button2
        sp = it.mapToScene(it.rect().center())
        p = self.panel_with_buttons.view.mapFromScene(sp)
        QtTest.QTest.mouseClick(
            self.panel_with_buttons.view.viewport(), QtCore.Qt.LeftButton, pos=p
        )