PySide6导入类后QListView点击事件失效,调试模式却正常
QListView点击事件在类导入后无响应(调试模式正常)
我需要实现点击QListView组件widget_list_files(显示PDF文件路径)时,更新QWebEngineView组件view展示对应的PDF文件。所有代码放在app.py中时功能正常,但将相同代码移到cms.py并以类导入后,QListView能正常加载内容,但点击事件无响应;奇怪的是在VSCode中设置断点调试时,导入的版本又能正常工作。
app.py 代码
from modm.functions.cms import cms from PyQt5.QtWidgets import (QMainWindow, QHBoxLayout, QVBoxLayout, QLineEdit, QPushButton, QListView, QTabWidget, QWidget) from PyQt5.QtCore import QDir from PyQt5.QtWebEngineWidgets import QWebEngineView from PyQt5.QtWebEngineSettings import QWebEngineSettings import sys class MainWindow(QMainWindow): def __init__(self): super(MainWindow, self).__init__() self.file_path = '/home/user/Downloads' layout_cms = QHBoxLayout() # Files Layout layout_files = QVBoxLayout() layout_files_search = QHBoxLayout() search_input_text = QLineEdit() search_input_text.setMaxLength(10) search_input_text.setPlaceholderText("Enter your text") layout_files_search.addWidget(search_input_text) search_button_search = QPushButton("Search") layout_files_search.addWidget(search_button_search) self.widget_list_files = QListView() self.widget_list_files.clicked.connect(self.open_document) self.model_files = QFileSystemModel() self.model_files.setNameFilterDisables(False) self.model_files.setFilter(QDir.Files) self.model_files.setNameFilters(["*.pdf"]) layout_files.addLayout(layout_files_search) layout_files.addWidget(self.widget_list_files) layout_cms.addLayout(layout_files, stretch=2) # Document Layout self.view = QWebEngineView() self.view.settings().setAttribute(QWebEngineSettings.PluginsEnabled, True) self.view.settings().setAttribute(QWebEngineSettings.PdfViewerEnabled, True) layout_document = QVBoxLayout() layout_document.addWidget(self.view) # Document Layout -> buttons layout_document_buttons = QHBoxLayout() document_button_merge = QPushButton("Merge") layout_document_buttons.addWidget(document_button_merge) layout_document.addLayout(layout_document_buttons) layout_cms.addLayout(layout_document, stretch=3) self.model_files.setRootPath(self.file_path) self.widget_list_files.setModel(self.model_files) self.widget_list_files.setRootIndex(self.model_files.index(self.file_path)) self.widget_cms = QWidget() self.widget_cms.setLayout(layout_cms) content_cms = cms() # Tab Menu tab_menu = QTabWidget() tab_menu.setTabPosition(QTabWidget.West) tab_menu.setMovable(True) # 导入的cms版本 tab_menu.addTab(content_cms.widget_cms, 'CMS') # 当前文件内的版本 tab_menu.addTab(self.widget_cms, 'Merge') self.setCentralWidget(tab_menu) def open_document(self, index): self.view.setUrl(f"file://{self.model_files.filePath(index)}") def run(): app = QApplication(sys.argv) window = MainWindow() window.show() app.exec() if __name__ == '__main__': run()
cms.py 代码
from PyQt5.QtWidgets import (QHBoxLayout, QVBoxLayout, QLineEdit, QPushButton, QListView, QWidget) from PyQt5.QtCore import QDir from PyQt5.QtWebEngineWidgets import QWebEngineView from PyQt5.QtWebEngineSettings import QWebEngineSettings class cms(): def __init__(self): self.file_path = '/home/user/Downloads' layout_cms = QHBoxLayout() # Files Layout layout_files = QVBoxLayout() layout_files_search = QHBoxLayout() search_input_text = QLineEdit() search_input_text.setMaxLength(10) search_input_text.setPlaceholderText("Enter your text") layout_files_search.addWidget(search_input_text) search_button_search = QPushButton("Search") layout_files_search.addWidget(search_button_search) self.widget_list_files = QListView() self.widget_list_files.clicked.connect(self.open_document) self.model_files = QFileSystemModel() self.model_files.setNameFilterDisables(False) self.model_files.setFilter(QDir.Files) self.model_files.setNameFilters(["*.pdf"]) layout_files.addLayout(layout_files_search) layout_files.addWidget(self.widget_list_files) layout_cms.addLayout(layout_files, stretch=2) # Document Layout self.view = QWebEngineView() self.view.settings().setAttribute(QWebEngineSettings.PluginsEnabled, True) self.view.settings().setAttribute(QWebEngineSettings.PdfViewerEnabled, True) layout_document = QVBoxLayout() layout_document.addWidget(self.view) # Document Layout -> buttons layout_document_buttons = QHBoxLayout() document_button_merge = QPushButton("Merge") layout_document.addLayout(layout_document_buttons) layout_cms.addLayout(layout_document, stretch=3) self.model_files.setRootPath(self.file_path) self.widget_list_files.setModel(self.model_files) self.widget_list_files.setRootIndex(self.model_files.index(self.file_path)) self.widget_cms = QWidget() self.widget_cms.setLayout(layout_cms) def open_document(self, index): # 如果在这行和__init__里随便设个断点,调试模式下这个版本也能正常工作 self.view.setUrl(f"file://{self.model_files.filePath(index)}")
问题原因与解决方法
这是Python垃圾回收机制导致的信号槽连接失效问题:
- 在
app.py中,content_cms = cms()创建的实例仅被用来获取widget_cms,之后没有任何引用指向该实例。 - 非调试模式下,Python会自动回收无引用的对象,
cms实例被销毁后,其内部的信号槽连接(clicked.connect(self.open_document))也会失效,导致点击事件无响应。 - 调试模式下,断点会暂停程序执行,阻止垃圾回收,实例得以保留,因此功能正常。
解决方法:给cms实例保留一个引用,避免被垃圾回收。修改app.py中的对应代码段:
# 替换原有的content_cms = cms() self.content_cms = cms() # Tab Menu tab_menu = QTabWidget() tab_menu.setTabPosition(QTabWidget.West) tab_menu.setMovable(True) # 导入的cms版本 tab_menu.addTab(self.content_cms.widget_cms, 'CMS')
内容的提问来源于stack exchange,提问作者schumischumi
相关产品推荐
相关产品推荐

