簡體   English   中英

為什么我會在 pytest-qt 中收到這個“包裝的 C/C++ 對象......已被刪除”的錯誤?

[英]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類型的對象,然后調用該方法,根本沒有LogTableViewLogTableView導致錯誤。

在運行這個:

>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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM