我的主 GUI 中有一个表格。我想测试我使用右键单击项目时出现的菜单删除表中项目的能力。我正在使用 pytest-qt 进行测试。在单击小部件(例如按钮)时,使用 qtbot.mouseClick 似乎效果很好,但是当我尝试向它传递一个表格项时,它会给我一个类型错误(由于表格项不是小部件)。给我错误的代码行如下:
qtbot.mouseClick(maingui.tablename.item(row, col), Qt.RightButton)
出现错误:
TypeError: arguments did not match any overloaded call:
mouseClick(QWidget, Qt.MouseButton, modifier: Union[Qt.KeyboardModifiers, Qt.KeyboardModifier] = Qt.KeyboardModifiers(), pos: QPoint = QPoint(), delay: int = -1): argument 1 has unexpected type 'QTableWidgetItem'
鉴于文档,这个错误对我来说很有意义。我的问题是,有没有办法可以做到这一点?
我认为它不应该与问题相关,但是通过右键单击表项调用的函数使用 QPoint 装饰器。我的代码对右键单击的反应如下:
@pyqtSlot(QPoint)
def on_tablename_customContextMenuRequested(self, point):
current_cell = self.tablename.itemAt(point)
if current_cell:
row = current_cell.row()
deleteAction = QAction('Delete item', self)
editAction = QAction('Edit item', self)
menu.addAction(deleteAction)
menu.addAction(editAction)
action = menu.exec_(self.tablename.mapToGlobal(point))
if action == deleteAction:
# <do delete stuff>
elif action == editAction:
# <do edit stuff>
编辑:我可以使用 eyllanesc 的建议在表格中选择一个项目,但是右键单击该项目不会显示自定义上下文菜单。这是我的问题的最小可重现示例,使用带有自定义上下文菜单的两列表。我需要能够在测试期间自动选择“删除项目”选项:
from time import sleep
import pytest
from PyQt5.QtCore import QPoint, Qt, QTimer, pyqtSlot
from PyQt5.QtWidgets import QMainWindow, QTableWidgetItem, QMenu, QAction, QAbstractItemView
from tests.test_ui_generated import ui_minimum_main
pytest.main(['-s'])
class TestTable(ui_minimum_main.Ui_minimum_table, QMainWindow):
def __init__(self, args):
QMainWindow.__init__(self)
self.setupUi(self)
self.table_minimum.setContextMenuPolicy(Qt.CustomContextMenu)
self.table_minimum.setColumnCount(2)
self.detectorHorizontalHeaderLabels = ['Col A', 'Col B']
self.table_minimum.setHorizontalHeaderLabels(self.detectorHorizontalHeaderLabels)
self.table_minimum.setSelectionMode(QAbstractItemView.ExtendedSelection)
self.table_minimum.setSelectionBehavior(QAbstractItemView.SelectRows)
self.table_minimum.setRowCount(1)
self.table_minimum.setRowHeight(0, 22)
item = QTableWidgetItem('test_col_a')
item.setData(Qt.UserRole, 'test_col_a')
self.table_minimum.setItem(0, 0, item)
item = QTableWidgetItem('test_col_b')
item.setData(Qt.UserRole, 'test_col_b')
self.table_minimum.setItem(0, 1, item)
self.table_minimum.resizeRowsToContents()
@pyqtSlot(QPoint)
def on_table_minimum_customContextMenuRequested(self, point):
print('context_menu_requested')
current_cell = self.table_minimum.itemAt(point)
if current_cell:
deleteAction = QAction('Option A- Delete Row', self)
nothingAction = QAction('Option B- Nothing', self)
menu = QMenu(self.table_minimum)
menu.addAction(deleteAction)
menu.addAction(nothingAction)
action = self.menu.exec_(self.table_minimum.mapToGlobal(point))
if action == deleteAction:
self.table_minimum.setRowCount(0)
return
def test_detector_create_delete_gui(qtbot):
w = TestTable([])
qtbot.addWidget(w)
w.show()
qtbot.waitForWindowShown(w)
sleep(.5)
item = w.table_minimum.item(0, 0)
assert item is not None
def interact_with_menu():
# ???????
pass
rect = w.table_minimum.visualItemRect(item)
QTimer.singleShot(100, interact_with_menu)
qtbot.mouseClick(w.table_minimum.viewport(), Qt.RightButton, pos=rect.center())