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

如何实现QTreeView中项的前后切换(附PyQt5代码示例)

QTreeView 元素前后切换实现方案

针对你使用QStandardItemModel和QTreeView时遇到的前后切换元素问题,以下是修正后的完整代码,核心是利用QTreeView自带的moveCursor方法实现符合默认导航逻辑的前后切换:

import sys
from PyQt5.QtWidgets import QApplication, QMainWindow, QTreeView, QPushButton, QVBoxLayout, QWidget
from PyQt5.Qt import QStandardItemModel, QStandardItem
from PyQt5.QtCore import Qt


class AppDemo(QMainWindow):
    def __init__(self):
        super().__init__()
        self.setWindowTitle('World Country Diagram')
        self.resize(500, 700)

        self.treeView = QTreeView()
        self.treeView.setHeaderHidden(True)

        treeModel = QStandardItemModel()
        self.rootNode = treeModel.invisibleRootItem()

        # America
        america = QStandardItem('America')

        california = QStandardItem('California')
        america.appendRow(california)

        oakland = QStandardItem('Oakland')
        sanfrancisco = QStandardItem('San Francisco')
        sanjose = QStandardItem('San Jose')

        california.appendRow(oakland)
        california.appendRow(sanfrancisco)
        california.appendRow(sanjose)

        texas = QStandardItem('Texas')
        america.appendRow(texas)

        austin = QStandardItem('Austin')
        houston = QStandardItem('Houston')
        dallas = QStandardItem('dallas')

        texas.appendRow(austin)
        texas.appendRow(houston)
        texas.appendRow(dallas)

        # Canada
        canada = QStandardItem('Canada')
        alberta = QStandardItem('Alberta')
        bc = QStandardItem('British Columbia')
        ontario = QStandardItem('Ontario')
        canada.appendRows([alberta, bc, ontario])


        self.rootNode.appendRow(america)
        self.rootNode.appendRow(canada)

        self.treeView.setModel(treeModel)
        self.treeView.expandAll()
        self.treeView.selectionModel().selectionChanged.connect(self.display)
        self.button_next = QPushButton("Next", self)
        self.button_next.clicked.connect(self.next)
        self.button_before = QPushButton("Before", self)
        # 修正:绑定到before方法
        self.button_before.clicked.connect(self.before)
        layout = QVBoxLayout()
        layout.addWidget(self.button_next)
        layout.addWidget(self.button_before)
        layout.addWidget(self.treeView)
        window = QWidget()
        window.setLayout(layout)
        self.setCentralWidget(window)

    # 修正:selectionChanged信号传递两个参数
    def display(self, selected, deselected):
        selection_model = self.treeView.selectionModel()
        index = selection_model.currentIndex()
        print(self.treeView.model().itemData(index))

    def next(self):
        # 使用moveCursor获取下一个索引,遵循TreeView默认导航逻辑
        target_index = self.treeView.moveCursor(QTreeView.MoveNext, Qt.NoModifier)
        if target_index.isValid():
            self.treeView.setCurrentIndex(target_index)
        
    def before(self):
        # 使用moveCursor获取上一个索引
        target_index = self.treeView.moveCursor(QTreeView.MovePrevious, Qt.NoModifier)
        if target_index.isValid():
            self.treeView.setCurrentIndex(target_index)


app = QApplication(sys.argv)

demo = AppDemo()
demo.show()

sys.exit(app.exec_())

关键说明

  1. 修正绑定错误:原代码中button_before的点击信号错误绑定到了next方法,已修正为绑定before方法。
  2. 使用moveCursor方法:
    • QTreeView.moveCursor()方法会自动遵循TreeView的默认导航逻辑(比如优先进入展开的子节点、遍历同层级兄弟、回溯到父节点的下一个兄弟等),和键盘上下键的行为完全一致,无需手动遍历树结构。
    • 传入QTreeView.MoveNext获取下一个元素索引,QTreeView.MovePrevious获取上一个元素索引,Qt.NoModifier表示无键盘修饰符。
  3. 索引有效性判断:获取目标索引后先判断isValid(),避免切换到无效索引(比如已经是第一个/最后一个元素时)。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.20 01:20:32