You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

QListView复杂自定义委托内点击QTableView无法选中父行问题

问题原因

  • QTableView属于滚动区控件,实际响应用户交互的是其内部的viewport子部件,仅给QTableView本身设置NoFocus不会阻止viewport消费鼠标点击事件
  • 点击事件被viewport拦截后不会向上冒泡到父级ItemEditor,因此QListView无法捕获点击,也就不会触发clicked信号和行选中逻辑

解决方法

根据你对QTableView的交互需求,可以二选一:

方案A:无需保留QTableView交互能力(仅作数据展示)

直接设置QTableView的鼠标事件穿透属性,所有点击会直接透传给父级行部件,无需额外逻辑,在ItemEditor的__init__里添加一行即可:

self.table_view.setAttribute(QtCore.Qt.WA_TransparentForMouseEvents)

方案B:需要保留QTableView的滚动、单元格点击等交互能力

使用事件过滤器将鼠标点击事件同时转发给父级行部件,既不影响QTableView本身的功能,也能触发QListView的行选中,修改如下:

  1. 头部补充导入QtGui模块
from PyQt5 import QtWidgets, QtCore, QtGui
  1. 修改ItemEditor类:
class ItemEditor(QWidget):
    def __init__(self, parent=None):
        super().__init__(parent)
        self.verticalLayout = QVBoxLayout(self)
        self.line_label = QLabel("This is a line", self)
        self.verticalLayout.addWidget(self.line_label)
        self.table_view = QTableView(self)
        self.table_view.setFocusPolicy(QtCore.Qt.NoFocus)
        self.table_view.viewport().setFocusPolicy(QtCore.Qt.NoFocus)
        self.table_view.setSizeAdjustPolicy(QtWidgets.QAbstractScrollArea.AdjustToContents)
        self.table_view.setSelectionMode(QtWidgets.QAbstractItemView.NoSelection)
        self.table_view.horizontalHeader().setVisible(False)
        self.table_view.verticalHeader().setVisible(False)
        self.verticalLayout.addWidget(self.table_view)
        # 给viewport安装事件过滤器
        self.table_view.viewport().installEventFilter(self)

    def eventFilter(self, watched, event):
        if watched == self.table_view.viewport() and event.type() == QtCore.QEvent.MouseButtonPress:
            # 转发点击事件到父级行容器
            forwarded_event = QtGui.QMouseEvent(
                event.type(), 
                self.mapFromGlobal(event.globalPos()), 
                event.globalPos(), 
                event.button(), 
                event.buttons(), 
                event.modifiers()
            )
            QtWidgets.QApplication.sendEvent(self.parent(), forwarded_event)
            # 不拦截原事件,保留给QTableView本身处理
        return super().eventFilter(watched, event)

修改完成后运行代码,点击QTableView区域就会正常触发change_line方法,也能正常选中对应行了。

内容的提问来源于stack exchange,提问作者AlexandreS

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.11 22:51:03