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

PyQt6 QTableView首次点击选中项selectedIndexes()返回空列表问题

问题根因

自定义mousePressEvent时的执行顺序错误:先发射了自定义信号,再调用父类QTableView.mousePressEvent。QTableView的选中状态更新逻辑是在父类的鼠标按下事件中执行的,首次点击时信号触发早于选中逻辑执行,因此selectedIndexes()返回空列表;第一次点击完成后选中状态被保留,后续点击时信号触发时能拿到上一次的选中结果,才会看起来“正常工作”。

解决方案

方案1:修正事件执行顺序

如果要保留自定义信号的实现,只需要调整代码顺序,先执行父类事件处理逻辑,待选中状态更新完成后再发射信号即可,无需提前设置默认选中行。
修改后的自定义表格类代码:

class TableViewClick(qt.QTableView):
    signal = pyqtSignal()

    def mousePressEvent(self, event):
        # 先执行父类默认逻辑,完成点击选中流程
        super().mousePressEvent(event)
        # 选中状态更新后再发射自定义信号
        self.signal.emit()

注意:用super()调用父类方法比直接写qt.QTableView.mousePressEvent(self, event)更符合Python面向对象的写法,后续类继承时不会出现逻辑异常。

方案2:使用原生信号(推荐)

完全不需要重写鼠标事件自定义信号,QTableView自带的clicked信号已经实现了点击表项后的触发逻辑,且触发时机在选中状态更新完成之后,还会自动将当前点击项的QModelIndex作为参数传出,直接就能拿到行号,代码更简洁稳定,也不会出现时序问题。
完整实现代码:

from PyQt6.QtCore import Qt, QModelIndex
from PyQt6.QtGui import QStandardItem, QStandardItemModel
from PyQt6 import QtWidgets as qt
import sys

class Main(qt.QMainWindow):
    def __init__(self):
        super().__init__()
        frame = qt.QFrame()
        self.setCentralWidget(frame)
        laymb = qt.QVBoxLayout(frame)
        model = QStandardItemModel()
        # 无需自定义TableView子类
        tabmb = qt.QTableView()
        tabmb.setModel(model)
        tabmb.setGridStyle(Qt.PenStyle(0))
        tabmb.setSelectionMode(qt.QTableView.SelectionMode(1))
        tabmb.setSelectionBehavior(tabmb.SelectionBehavior(1))
        laymb.addWidget(tabmb)
        subj = []
        for e in range(10):
            subj.append(QStandardItem('Testing...'))
        model.appendColumn(subj)
        # 直接绑定原生clicked信号
        tabmb.clicked.connect(self._click_table)

    def _click_table(self, index: QModelIndex):
        # 直接从参数获取点击行号,无需额外调用selectedIndexes
        click_row = index.row()
        print(f"当前点击行号:{click_row}")
        # 需要所有选中索引时再调用selectedIndexes即可
        # selected = self.sender().selectedIndexes()

app = qt.QApplication(sys.argv)
main_gui = Main()
main_gui.show()
sys.exit(app.exec())

该方案的优势:

  • 无需自定义子类,代码量更少,维护成本低
  • 原生信号自动处理了点击位置判断,点击表格空白区域不会触发逻辑
  • 直接传入点击项索引,不需要额外遍历选中列表,单选场景下更高效
  • 不存在事件调用时序问题,行为和Qt默认逻辑完全一致

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.28 11:51:21