如何解决PySide/Qt QColumnView点击上层空白处视图不更新问题?
QColumnView点击上层目录空白处不更新视图的解决方案
我在开发一款仿macOS Finder米勒列(Miller Columns)的文件浏览器,使用Qt的QColumnView搭配QFileSystemModel组件,但遇到了一个问题:当进入多层目录后,点击当前目录上层区域的空白处,视图不会切换到对应目录,仅会移除当前文件夹的高亮效果;点击根目录空白处时甚至不会触发任何事件。
解决方案
核心思路是重写QColumnView的mousePressEvent,手动处理空白区域的点击事件,定位到点击列对应的父目录索引并设置为当前选中项。
修改CustomColumns类如下:
from PySide6.QtCore import QPoint, Qt from PySide6.QtWidgets import QColumnView, QAbstractItemView class CustomColumns(QColumnView): def mousePressEvent(self, event): # 先处理默认的项点击逻辑 super().mousePressEvent(event) # 如果点击的是空白区域(未命中任何项) if event.button() == Qt.LeftButton: # 获取点击位置对应的子视图(列) view = self.viewAt(event.pos()) if view: # 获取该列的根索引(即对应上层目录的索引) root_index = view.rootIndex() # 如果根索引有效,设置为当前选中项 if root_index.isValid(): self.selectionModel().setCurrentIndex( root_index, QAbstractItemView.ClearAndSelect | QAbstractItemView.Rows )
完整修改后的MCVE
from pathlib import Path from PySide6.QtCore import QPoint, Qt from PySide6.QtWidgets import ( QApplication, QFileSystemModel, QColumnView, QMainWindow, QAbstractItemView ) class CustomColumns(QColumnView): def mousePressEvent(self, event): super().mousePressEvent(event) if event.button() == Qt.LeftButton: view = self.viewAt(event.pos()) if view: root_index = view.rootIndex() if root_index.isValid(): self.selectionModel().setCurrentIndex( root_index, QAbstractItemView.ClearAndSelect | QAbstractItemView.Rows ) class BrowserWindow(QMainWindow): def __init__(self, location=None): super().__init__() if location is None: location = Path.home() location = Path(location) self.setGeometry(625, 333, 1395, 795) self.setWindowTitle(location.name) self._root = str(location) self._files = QFileSystemModel() self._files.setRootPath(self._root) self._view = CustomColumns() self._view.setModel(self._files) self.setCentralWidget(self._view) def show(self): super().show() self._view.setRootIndex(self._files.index(self._root)) class FileBrowser(QApplication): def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) self.setQuitOnLastWindowClosed(False) self.window = BrowserWindow(location=Path.home()) self.window.show() def main(): app = FileBrowser() app.exec() if __name__ == "__main__": main()
效果说明
修改后,点击任意上层目录列的空白区域,视图会自动切换到该列对应的目录,完全匹配macOS Finder的米勒列交互逻辑。
内容的提问来源于stack exchange,提问作者Darrick Herwehe
相关产品推荐
相关产品推荐

