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

PySide6:如何通过上下箭头移动光标时选中表格行?按键事件未触发

问题解决:通过上下箭头键选中表格行

问题原因

你的keyPressEvent未触发,核心原因是当前焦点在QTableWidget控件上,而非主窗口。QTableWidget本身会处理上下箭头事件(仅移动单元格焦点),但不会自动选中整行,因此需要针对表格控件处理键盘事件。

解决方案1:自定义表格类重写键盘事件

创建继承自QTableWidget的自定义类,重写keyPressEvent方法,在上下箭头按下时选中对应行:

import sys

from PySide6 import QtCore
from PySide6.QtGui import QKeyEvent
from PySide6.QtWidgets import QMainWindow, QApplication, QTableWidgetItem, QTableWidget, QVBoxLayout, QWidget
from loguru import logger


class CustomTableWidget(QTableWidget):
    def keyPressEvent(self, event: QKeyEvent) -> None:
        # 处理上下箭头逻辑
        if event.key() in (QtCore.Qt.Key_Up, QtCore.Qt.Key_Down):
            # 先执行表格默认的焦点移动逻辑
            super().keyPressEvent(event)
            # 获取当前焦点行并选中整行
            current_row = self.currentRow()
            self.selectRow(current_row)
            logger.info(f"选中行:{current_row}")
        else:
            # 其他按键交给默认处理
            super().keyPressEvent(event)


class TableWindow(QMainWindow):
    def __init__(self, data, parent=None):
        super(TableWindow, self).__init__(parent)

        # 使用自定义表格控件
        self.table_widget = CustomTableWidget()
        self.table_widget.cellClicked.connect(self.clicked)

        self.populate_cells(data)

        layout = QVBoxLayout()
        layout.addWidget(self.table_widget)

        widget = QWidget()
        widget.setLayout(layout)
        self.setCentralWidget(widget)
        # 初始化时给表格设置焦点,避免手动点击
        self.table_widget.setFocus()

    def clicked(self, row, col):
        logger.info(f"{row}, {col}")
        self.table_widget.selectRow(row)

    def populate_cells(self, data):
        self.table_widget.setRowCount(len(data))
        self.table_widget.setColumnCount(len(data[0]))
        for row in range(len(data)):
            for col in range(len(data[0])):
                value = data[row][col]
                self.table_widget.setItem(row, col, QTableWidgetItem(value))


if __name__ == "__main__":
    data_sample = [
        ["customer1", "address1"],
        ["customer2", "address2"]
    ]
    app = QApplication(sys.argv)
    window = TableWindow(data_sample)
    window.show()
    sys.exit(app.exec())

解决方案2:给表格安装事件过滤器

如果不想自定义表格类,可在主窗口中给QTableWidget安装事件过滤器,拦截键盘事件:

import sys

from PySide6 import QtCore
from PySide6.QtGui import QKeyEvent
from PySide6.QtWidgets import QMainWindow, QApplication, QTableWidgetItem, QTableWidget, QVBoxLayout, QWidget
from loguru import logger


class TableWindow(QMainWindow):
    def __init__(self, data, parent=None):
        super(TableWindow, self).__init__(parent)

        self.table_widget = QTableWidget()
        self.table_widget.cellClicked.connect(self.clicked)
        # 给表格安装事件过滤器
        self.table_widget.installEventFilter(self)

        self.populate_cells(data)

        layout = QVBoxLayout()
        layout.addWidget(self.table_widget)

        widget = QWidget()
        widget.setLayout(layout)
        self.setCentralWidget(widget)
        # 初始化时给表格设置焦点
        self.table_widget.setFocus()

    def eventFilter(self, obj, event):
        if obj == self.table_widget and event.type() == QtCore.QEvent.KeyPress:
            if event.key() in (QtCore.Qt.Key_Up, QtCore.Qt.Key_Down):
                # 执行表格默认的焦点移动逻辑
                self.table_widget.keyPressEvent(event)
                # 选中当前焦点所在行
                current_row = self.table_widget.currentRow()
                self.table_widget.selectRow(current_row)
                logger.info(f"选中行:{current_row}")
                return True
        # 非目标事件交给父类处理
        return super().eventFilter(obj, event)

    def clicked(self, row, col):
        logger.info(f"{row}, {col}")
        self.table_widget.selectRow(row)

    def populate_cells(self, data):
        self.table_widget.setRowCount(len(data))
        self.table_widget.setColumnCount(len(data[0]))
        for row in range(len(data)):
            for col in range(len(data[0])):
                value = data[row][col]
                self.table_widget.setItem(row, col, QTableWidgetItem(value))


if __name__ == "__main__":
    data_sample = [
        ["customer1", "address1"],
        ["customer2", "address2"]
    ]
    app = QApplication(sys.argv)
    window = TableWindow(data_sample)
    window.show()
    sys.exit(app.exec())

额外说明

两种方案均保留了表格默认的上下箭头焦点移动逻辑,同时添加了整行选中的功能,和点击单元格时的行为完全一致。初始化时设置self.table_widget.setFocus()可避免用户手动点击表格获取焦点。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.16 06:55:18