[英]Why am I getting this "wrapped C/C++ object ... has been deleted" error with pytest-qt?
請注意:這是在W10 上。 這可能很重要。
Python:3.9.4 pytest:6.2.5 pytest-qt:4.0.2
我已經使用 pytest-qt 大約一個星期來開始開發 PyQt5 應用程序。 有一些令人困惑的問題,但沒有一個比這個問題更令人困惑。
我的應用程序代碼:
class LogTableView(QtWidgets.QTableView):
def __init__(self, parent, *args, **kwargs):
super().__init__(parent, *args, **kwargs)
def resizeEvent(self, resize_event):
super().resizeEvent(resize_event)
# self.resizeRowsToContents()
需要添加上面的最后一行。 因此,我使用 TDD 方法開始編寫測試:
def test_resize_event_should_result_in_resize_rows(request, qtbot):
t_logger.info(f'\n>>>>>> test name: {request.node.originalname}')
table_view = logger_table.LogTableView(QtWidgets.QSplitter())
# with unittest.mock.patch.object(table_view, 'resizeRowsToContents') as mock_resize:
# with unittest.mock.patch('logger_table.LogTableView.resizeRowsToContents') as mock_resize:
table_view.resizeEvent(QtGui.QResizeEvent(QtCore.QSize(10, 10), QtCore.QSize(20, 20)))
注意注釋掉的行顯示了我一直在嘗試的事情。 但是你可以看到,即使只是創建一個LogTableView
類型的對象,然后調用該方法,根本沒有LogTableView
, LogTableView
導致錯誤。
在運行這個:
>pytest -s -v -k test_logger_table.py
我明白了:
...
self = <logger_table.LogTableView object at 0x000002B672697670>
resize_event = <PyQt5.QtGui.QResizeEvent object at 0x000002B672743940>
def resizeEvent(self, resize_event):
> super().resizeEvent(resize_event)
E RuntimeError: wrapped C/C++ object of type LogTableView has been deleted
...
有沒有人知道這是關於什么的?
PS FWIW,出於絕望,我什至嘗試過:
super(LogTableView, self).resizeEvent(resize_event)
...同樣的錯誤。
在子構造函數中創建父對象不是一個好主意。
請記住,PyQt 是一個binding ,Python 中使用的每個引用都是 Qt 對象的包裝器:如果在 C++ 端刪除該對象,則 Python 引用仍然存在,但任何嘗試使用其函數都會導致上述 RuntimeError。
在你的情況,有一個為蟒側父,只有Qt的一側的指針,這是不夠的,以避免垃圾收集沒有持久參考:只有父對象取得所有權的QT(這就是為什么你能避免的持久引用子 Qt 對象),而不是相反。 問題是孩子認為它有一個父級(因為它在創建時有一個),但與此同時,一旦返回子構造函數,父級就被刪除了。
只需為父級創建一個局部變量。
def test_resize_event_should_result_in_resize_rows(request, qtbot):
t_logger.info(f'\n>>>>>> test name: {request.node.originalname}')
parent = QtWidgets.QSplitter()
table_view = logger_table.LogTableView(parent)
# ...
除了主題的問題,從技術上講,使用非常具體的小部件(例如 QSplitter)作為父級是沒有意義的(特別是考慮到為了正確使用,小部件應該添加addWidget()
,因為只有addWidget()
是對分離器毫無意義); 如果您需要父母,只需使用基本的 QWidget。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.