本页面

文件系统资源管理器

一个桌面 QML 应用程序,利用定制的Qt Quick Controls 显示文件系统中的文本文件。

文件系统浏览器用户界面

文件系统资源管理器示例采用现代布局,由三个主要部分组成:左侧基于图标的侧边栏、从QFileSystemModel 显示文件系统的可调整大小的TreeView ,以及显示所选文本文件的TextArea 。定制的快速控件和无框架窗口,加上专门的窗口装饰,确保了在所有操作系统上都能获得统一的外观和感觉。从命令行启动该程序时,可以提供一个初始目录作为参数。TreeView 将使用该初始目录设置显示目录结构的起点。

运行示例

要从 Qt Creator,打开Welcome 模式,并从Examples 中选择示例。更多信息,请参阅Qt Creator: 教程:构建并运行

现代布局和结构

首先,该示例在整个单例 QML 对象中提供了颜色。这是为了确保对应用程序外观的结构化控制。

pragma Singleton

QtObject {
    readonly property color background: "#292828"
    readonly property color surface1: "#171819"
    readonly property color surface2: "#090A0C"
    readonly property color text: "#D4BE98"
    readonly property color textFile: "#E1D2B7"
    readonly property color disabledText: "#2C313A"
    readonly property color selection: "#4B4A4A"
    readonly property color active: "#292828"
    readonly property color inactive: "#383737"
    readonly property color folder: "#383737"
    readonly property color icon: "#383737"
    readonly property color iconIndicator: "#D5B35D"
    readonly property color color1: "#A7B464"
    readonly property color color2: "#D3869B"
}

本例使用ApplicationWindow 内的FramelessWindowHint 标志创建自定义装饰,而不是依赖操作系统的窗口装饰。为了实现与窗口的等效交互,示例覆盖了自定义MenuBarcontentItem 属性,并显示信息文本以及拖动或关闭应用程序的交互可能性。内联组件简化了这一过程。

            component InteractionButton: Rectangle {
                id: interactionButton

                signal action()
                property alias hovered: hoverHandler.hovered

                Layout.fillHeight: true
                Layout.preferredWidth: height

                color: hovered ? Colors.background : "transparent"
                HoverHandler {
                    id: hoverHandler
                }
                TapHandler {
                    id: tapHandler
                    onTapped: interactionButton.action()
                }
            }

            InteractionButton {
                id: minimize

                onAction: root.dragWindow.showMinimized()
                Rectangle {
                    anchors.centerIn: parent
                    color: parent.hovered ? Colors.iconIndicator : Colors.icon
                    height: 2
                    width: parent.height - 14
                }
            }

            InteractionButton {
                id: maximize
    ...

左侧的侧边栏包括顶部的可选中导航按钮和底部的单击按钮。ButtonGroup 和容器用于确保任何时候只有一个条目处于活动状态。然后,可以使用当前位置的属性别名和StackLayout 来提供不同的视图。

通过这种技术,您可以在StackLayout 中添加另一个按钮和相应的元素,从而扩展功能。

                StackLayout {
                    anchors.fill: parent
                    currentIndex: sidebar.currentTabIndex

                    // Shows the help text.
                    Text {
                        text: qsTr("This example shows how to use and visualize the file system.\n\n"
                                 + "Customized Qt Quick Components have been used to achieve this look.\n\n"
                                 + "You can edit the files but they won't be changed on the file system.\n\n"
                                 + "Click on the folder icon to the left to get started.")
                        wrapMode: TextArea.Wrap
                        color: Colors.text
                    }

                    // Shows the files on the file system.
                    FileSystemView {
                        id: fileSystemView
                        color: Colors.surface1
                        onFileClicked: path => root.currentFilePath = path
                    }
                }

除了一些信息文本外,StackLayout 还包括FileSystemView。这个自定义组件显示文件和文件夹,并从C++ 模型中填充数据。然后,您可以选择文件并相应地读取它们。

QString FileSystemModel::readFile(const QString &filePath)
{
    // Don't issue errors for an empty path, as the initial binding
    // will result in an empty path, and that's OK.
    if (filePath.isEmpty())
        return {};

    QFile file(filePath);

    if (file.size() >= 2'000'000)
        return tr("File size is too big.\nYou can read files up to %1 MB.").arg(2);

    static const QMimeDatabase db;
    const QMimeType mime = db.mimeTypeForFile(QFileInfo(file));

    // Check if the mimetype is supported and return the content.
    const auto mimeTypesForFile = mime.parentMimeTypes();
    for (const auto &m : mimeTypesForFile) {
        if (m.contains("text", Qt::CaseInsensitive)
                || mime.comment().contains("text", Qt::CaseInsensitive)) {
            if (!file.open(QIODevice::ReadOnly | QIODevice::Text))
                return tr("Error opening the File!");

            QTextStream stream(&file);
            return stream.readAll();
        }
    }
    return tr("Filetype not supported!");
}

右键单击TreeView 中的文件夹会弹出Menu ,可以控制TreeViewrootIndex 属性。

            MyMenu {
                id: contextMenu
                Action {
                    text: qsTr("Set as root index")
                    onTriggered: {
                        fileSystemTreeView.rootIndex = fileSystemTreeView.index(treeDelegate.row, 0)
                    }
                }
                Action {
                    text: qsTr("Reset root index")
                    onTriggered: fileSystemTreeView.rootIndex = undefined
                }
            }
        }

SplitView 您可以动态共享StackLayout 和编辑器之间的空间。编辑器包含TextArea ,可显示打开的文件,并提供编辑文本文件所需的所有功能。此外,编辑器还提供行号,可在Menu.

            Editor {
                id: editor
                showLineNumbers: root.showLineNumbers
                currentFilePath: root.currentFilePath
                SplitView.fillWidth: true
                SplitView.fillHeight: true
            }

自定义组件

要更好地了解自定义过程,请先阅读 "自定义控件"一文。本示例使用了可重复使用的自定义组件。

例如,MyMenu 组件定制了菜单的background 属性、其委托的contentItembackground 属性。

// Copyright (C) 2023 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause

import QtQuick
import QtQuick.Controls.Basic
import FileSystemModule

Menu {
    id: root

    delegate: MenuItem {
        id: menuItem
        contentItem: Item {
            Text {
                anchors.verticalCenter: parent.verticalCenter
                anchors.left: parent.left
                anchors.leftMargin: 5

                text: menuItem.text
                color: enabled ? Colors.text : Colors.disabledText
            }
            Rectangle {
                id: indicator

                anchors.verticalCenter: parent.verticalCenter
                anchors.right: parent.right
                width: 6
                height: parent.height

                visible: menuItem.highlighted
                color: Colors.color2
            }
        }
        background: Rectangle {
            implicitWidth: 210
            implicitHeight: 35
            color: menuItem.highlighted ? Colors.active : "transparent"
        }
    }
    background: Rectangle {
        implicitWidth: 210
        implicitHeight: 35
        color: Colors.surface2
    }
}

另一个例子是FileSystemView 内的ScrollIndicator 的定制,它使用了定制的动画。这里,该示例覆盖了contentItem

        ScrollIndicator.vertical: ScrollIndicator {
            active: true
            implicitWidth: 15

            contentItem: Rectangle {
                implicitWidth: 6
                implicitHeight: 6

                color: Colors.color1
                opacity: fileSystemTreeView.movingVertically ? 0.5 : 0.0

                Behavior on opacity {
                    OpacityAnimator {
                        duration: 500
                    }
                }
            }
        }

Python 版本

如果您对本示例的 Python 版本感兴趣,可以在此处找到。它展示了Qt for Python 的用法,并演示了如何使用它创建相同的应用程序。

此外,还提供了详细的教程,逐步说明如何使用其他功能扩展此示例。如果你想探索和学习更多有关在文件系统资源管理器现有功能基础上进行扩展的知识,本教程会对你有所帮助。

源文件

示例项目 @ code.qt.io

另请参阅 所有 Qt 示例Qt Quick Controls 示例

© 2026 The Qt Company Ltd. Documentation contributions included herein are the copyrights of their respective owners. The documentation provided herein is licensed under the terms of the GNU Free Documentation License version 1.3 as published by the Free Software Foundation. Qt and respective logos are trademarks of The Qt Company Ltd. in Finland and/or other countries worldwide. All other trademarks are property of their respective owners.