开源 C++ QT QML 开发(九)文件--文本和二进制

文章的目的为了记录使用QT QML开发学习的经历。开发流程和要点有些记忆模糊,赶紧记录,防止忘记。

相关链接:

开源 C++ QT QML 开发(一)基本介绍

开源 C++ QT QML 开发(二)工程结构

开源 C++ QT QML 开发(三)常用控件

开源 C++ QT QML 开发(四)复杂控件--Listview

开源 C++ QT QML 开发(五)复杂控件--Gridview

开源 C++ QT QML 开发(六)自定义控件--波形图

开源 C++ QT QML 开发(七)自定义控件--仪表盘

开源 C++ QT QML 开发(八)自定义控件--圆环

开源 C++ QT QML 开发(九)文件--文本和二进制

推荐链接:

开源 C# 快速开发(一)基础知识

开源 C# 快速开发(二)基础控件

开源 C# 快速开发(三)复杂控件

开源 C# 快速开发(四)自定义控件--波形图

开源 C# 快速开发(五)自定义控件--仪表盘

开源 C# 快速开发(六)自定义控件--圆环

开源 C# 快速开发(七)通讯--串口

开源 C# 快速开发(八)通讯--Tcp服务器端

开源 C# 快速开发(九)通讯--Tcp客户端

开源 C# 快速开发(十)通讯--http客户端

开源 C# 快速开发(十一)线程

开源 C# 快速开发(十二)进程监控

开源 C# 快速开发(十三)进程--管道通讯

开源 C# 快速开发(十四)进程--内存映射

开源 C# 快速开发(十五)进程--windows消息

开源 C# 快速开发(十六)数据库--sqlserver增删改查

本章节主要内容是:实现了一个简单文件编辑器应用程序,可以对文本文件和二进制文件打开和保存。

1.代码分析

2.所有源码

3.效果演示

一、代码分析

  1. FileHandler 头文件分析

1.1 类声明和属性定义

复制代码
class FileHandler : public QObject
{
    Q_OBJECT
    Q_PROPERTY(QString fileName READ fileName NOTIFY fileNameChanged)
    Q_PROPERTY(bool isBinary READ isBinary NOTIFY isBinaryChanged)
    Q_PROPERTY(bool fileModified READ fileModified NOTIFY fileModifiedChanged)
    Q_PROPERTY(QVariantList hexData READ hexData NOTIFY hexDataChanged)
    Q_PROPERTY(QString fileContent READ fileContent NOTIFY fileContentChanged)

分析:

使用 Qt 属性系统,所有属性都是只读的(只有 READ,没有 WRITE)

NOTIFY 信号确保属性变化时 QML 能自动更新

QVariantList 用于在 C++ 和 QML 之间传递复杂数据

1.2 信号定义

复制代码
signals:
    void fileNameChanged();
    void isBinaryChanged();
    void fileModifiedChanged();
    void hexDataChanged();
    void fileContentChanged();
    void fileOpened(const QString &fileName, bool isBinary);
    void fileSaved(const QString &fileName);
    void fileClosed();
    void errorOccurred(const QString &errorMessage);

分析:

前5个信号对应属性变化通知

后4个信号是业务逻辑事件通知

fileOpened 和 errorOccurred 携带参数传递详细信息

  1. FileHandler 实现文件分析

2.1 构造函数

复制代码
FileHandler::FileHandler(QObject *parent)
    : QObject(parent)
    , m_isBinary(false)
    , m_fileModified(false)
{
}

分析:

初始化成员变量,默认文件类型为文本,未修改状态

2.2 openFile 函数

复制代码
bool FileHandler::openFile(const QString &filePath)
{
    QFile file(filePath);
    if (!file.exists()) {
        emit errorOccurred(tr("文件不存在: %1").arg(filePath));
        return false;
    }

文件存在性检查:

使用 QFile::exists() 检查文件是否存在

如果不存在,发射错误信号并返回 false

复制代码
 if (!file.open(QIODevice::ReadOnly)) {
        emit errorOccurred(tr("无法打开文件: %1").arg(filePath));
        return false;
    }

文件打开检查:

尝试以只读模式打开文件

如果打开失败(权限问题、文件被占用等),发射错误信号

复制代码
    m_fileName = filePath;
    m_isBinary = isBinaryFile(filePath);

    if (m_isBinary) {
        // 读取二进制文件
        QByteArray data = file.readAll();
        m_originalData = data;
        m_fileContent.clear();
        processBinaryData(data);
    } else {
        // 读取文本文件
        QTextStream stream(&file);
        stream.setCodec("UTF-8");
        m_fileContent = stream.readAll();
        m_originalData = m_fileContent.toUtf8();

        // 清空二进制数据
        m_hexData.clear();
        emit hexDataChanged();

        emit fileContentChanged();
        emit fileOpened(filePath, false);
    }

文件内容处理:

二进制文件:直接读取原始数据,调用 processBinaryData 处理

文本文件:使用 QTextStream 以 UTF-8 编码读取,保存内容和原始数据

清理不相关的数据并发射相应信号

复制代码
file.close();
    m_fileModified = false;

    emit fileNameChanged();
    emit isBinaryChanged();
    emit fileModifiedChanged();

    return true;
}

收尾工作:

关闭文件,重置修改状态

发射属性变化信号通知界面更新

2.3 processBinaryData 函数

复制代码
void FileHandler::processBinaryData(const QByteArray &data)
{
    m_hexData.clear();

    // 预分配空间,提高性能
    int lineCount = (data.size() + 15) / 16; // 计算总行数
    m_hexData.reserve(lineCount);

    const uchar *bytes = reinterpret_cast<const uchar*>(data.constData());
    int dataSize = data.size();

性能优化:

预计算行数:每行16字节,计算需要的行数

预分配 QVariantList 容量避免重复分配

使用原始指针访问提高效率

复制代码
    for (int i = 0; i < dataSize; i += 16) {
        QString hexLine;
        hexLine.reserve(48); // 预分配空间:16字节 * 3字符

        for (int j = 0; j < 16 && i + j < dataSize; j++) {
            uchar byte = bytes[i + j];
            QString hexByte = QString("%1 ").arg(byte, 2, 16, QChar('0')).toUpper();
            hexLine.append(hexByte);
        }

        // 移除最后一个空格
        if (!hexLine.isEmpty() && hexLine.endsWith(' ')) {
            hexLine.chop(1);
        }

十六进制格式化:

每行处理最多16个字节

使用 QString::arg() 格式化为2位十六进制,不足补零

移除行末多余的空格

复制代码
        QVariantMap lineData;
        lineData["address"] = QString("%1").arg(i, 8, 16, QChar('0')).toUpper();
        lineData["hex"] = hexLine;

        m_hexData.append(lineData);
    }

    emit hexDataChanged();
    emit fileOpened(m_fileName, true);
}

数据结构构建:

使用 QVariantMap 存储每行的地址和十六进制数据

地址格式化为8位十六进制数

发射信号通知数据就绪2.4 saveFile 函数

复制代码
bool FileHandler::saveFile(const QString &content)
{
    if (m_fileName.isEmpty()) {
        emit errorOccurred(tr("没有指定文件名"));
        return false;
    }

    QFile file(m_fileName);
    if (!file.open(QIODevice::WriteOnly | QIODevice::Text)) {
        emit errorOccurred(tr("无法保存文件: %1").arg(m_fileName));
        return false;
    }

    QTextStream stream(&file);
    stream.setCodec("UTF-8");
    stream << content;
    file.close();

文本文件保存:

检查文件名有效性

以文本模式写入,使用 UTF-8 编码

使用 QTextStream 确保编码正确

复制代码
    m_fileContent = content;
    m_originalData = content.toUtf8();
    m_fileModified = false;

    emit fileContentChanged();
    emit fileSaved(m_fileName);
    emit fileModifiedChanged();

    return true;
}

状态更新:

更新内存中的内容和原始数据

重置修改标志

发射保存成功信号2.5 saveBinaryFile 函数

复制代码
bool FileHandler::saveBinaryFile(const QVariantList &hexData)
{
    // ... 文件名和文件打开检查类似 saveFile ...

    // 将十六进制数据转换回二进制
    QByteArray binaryData;
    for (const QVariant &line : hexData) {
        QString hexLine = line.toString();
        QByteArray lineData = hexStringToByteArray(hexLine);
        binaryData.append(lineData);
    }

    file.write(binaryData);
    file.close();

二进制数据重建:

遍历十六进制数据列表

调用 hexStringToByteArray 转换每行数据

直接写入二进制数据2.6 hexStringToByteArray 函数

复制代码
QByteArray FileHandler::hexStringToByteArray(const QString &hexString)
{
    QByteArray byteArray;
    QStringList hexBytes = hexString.split(' ', Qt::SkipEmptyParts);
    byteArray.reserve(hexBytes.size());

    for (const QString &hexByte : hexBytes) {
        bool ok;
        char byte = static_cast<char>(hexByte.toInt(&ok, 16));
        if (ok) {
            byteArray.append(byte);
        }
    }

    return byteArray;
}

十六进制解析:

按空格分割十六进制字符串

使用 toInt(&ok, 16) 将十六进制字符串转换为整数

只添加成功转换的字节2.7 isBinaryFile 函数

复制代码
bool FileHandler::isBinaryFile(const QString &filePath)
{
    QFileInfo fileInfo(filePath);
    QString extension = fileInfo.suffix().toLower();

    static const QStringList binaryExtensions = {
        "exe", "dll", "bin", "dat", "img", "so", "dylib",
        "jpg", "jpeg", "png", "gif", "bmp", "ico",
        "pdf", "doc", "docx", "xls", "xlsx",
        "zip", "rar", "7z", "tar", "gz"
    };

    return binaryExtensions.contains(extension);
}

文件类型判断:

基于文件扩展名的简单判断

使用 static const 避免重复构造列表

包含常见二进制文件格式

  1. QML 界面分析

3.1 二进制显示更新函数

复制代码
function updateBinaryDisplay() {
    var displayText = ""
    for (var i = 0; i < fileHandler.hexData.length; i++) {
        var line = fileHandler.hexData[i]
        displayText += line.address + "    " + line.hex + "\n"
    }
    textArea.text = displayText
}

显示格式化:

遍历十六进制数据,构建显示字符串

格式:地址 十六进制数据

每行以换行符结束3.2 保存二进制文件逻辑

复制代码
var lines = textArea.text.split('\n')
var hexData = []

for (var i = 0; i < lines.length; i++) {
    if (lines[i].trim() === "") continue
    var lineParts = lines[i].split('    ')
    if (lineParts.length >= 2) {
        hexData.push(lineParts[1].trim())
    }
}

fileHandler.saveBinaryFile(hexData)

数据提取:

从显示的文本中解析出十六进制数据

跳过空行,按分隔符分割地址和十六进制数据

只提取十六进制部分传递给 C++

二、所有源码

FileHandler.h文件源码

复制代码
#ifndef FILEHANDLER_H
#define FILEHANDLER_H

#include <QObject>
#include <QString>
#include <QByteArray>
#include <QFile>
#include <QTextStream>
#include <QDataStream>
#include <QVector>
#include <QVariantList>
#include <QFileInfo>

class FileHandler : public QObject
{
    Q_OBJECT
    Q_PROPERTY(QString fileName READ fileName NOTIFY fileNameChanged)
    Q_PROPERTY(bool isBinary READ isBinary NOTIFY isBinaryChanged)
    Q_PROPERTY(bool fileModified READ fileModified NOTIFY fileModifiedChanged)
    Q_PROPERTY(QVariantList hexData READ hexData NOTIFY hexDataChanged)
    Q_PROPERTY(QString fileContent READ fileContent NOTIFY fileContentChanged)

public:
    explicit FileHandler(QObject *parent = nullptr);

    QString fileName() const { return m_fileName; }
    bool isBinary() const { return m_isBinary; }
    bool fileModified() const { return m_fileModified; }
    QVariantList hexData() const { return m_hexData; }
    QString fileContent() const { return m_fileContent; }

    Q_INVOKABLE bool openFile(const QString &filePath);
    Q_INVOKABLE bool saveFile(const QString &content);
    Q_INVOKABLE bool saveBinaryFile(const QVariantList &hexData);
    Q_INVOKABLE void closeFile();
    Q_INVOKABLE bool isBinaryFile(const QString &filePath);

signals:
    void fileNameChanged();
    void isBinaryChanged();
    void fileModifiedChanged();
    void hexDataChanged();
    void fileContentChanged();
    void fileOpened(const QString &fileName, bool isBinary);
    void fileSaved(const QString &fileName);
    void fileClosed();
    void errorOccurred(const QString &errorMessage);

private:
    void processBinaryData(const QByteArray &data);
    QByteArray hexStringToByteArray(const QString &hexString);

    QString m_fileName;
    bool m_isBinary;
    bool m_fileModified;
    QByteArray m_originalData;
    QVariantList m_hexData;
    QString m_fileContent;
};

#endif // FILEHANDLER_H

FileHandler.cpp文件源码

复制代码
#include "filehandler.h"
#include <QDebug>
#include <QFileInfo>

FileHandler::FileHandler(QObject *parent)
    : QObject(parent)
    , m_isBinary(false)
    , m_fileModified(false)
{
}

bool FileHandler::openFile(const QString &filePath)
{
    QFile file(filePath);
    if (!file.exists()) {
        emit errorOccurred(tr("文件不存在: %1").arg(filePath));
        return false;
    }

    if (!file.open(QIODevice::ReadOnly)) {
        emit errorOccurred(tr("无法打开文件: %1").arg(filePath));
        return false;
    }

    m_fileName = filePath;
    m_isBinary = isBinaryFile(filePath);

    if (m_isBinary) {
        // 读取二进制文件 - 使用更高效的方式
        QByteArray data = file.readAll();
        m_originalData = data;
        m_fileContent.clear();
        processBinaryData(data);
    } else {
        // 读取文本文件
        QTextStream stream(&file);
        stream.setCodec("UTF-8");
        m_fileContent = stream.readAll();
        m_originalData = m_fileContent.toUtf8();

        // 清空二进制数据
        m_hexData.clear();
        emit hexDataChanged();

        // 发送文件内容变化信号
        emit fileContentChanged();

        // 发送信号通知文件已打开
        emit fileOpened(filePath, false);
    }

    file.close();
    m_fileModified = false;

    emit fileNameChanged();
    emit isBinaryChanged();
    emit fileModifiedChanged();

    return true;
}

bool FileHandler::saveFile(const QString &content)
{
    if (m_fileName.isEmpty()) {
        emit errorOccurred(tr("没有指定文件名"));
        return false;
    }

    QFile file(m_fileName);
    if (!file.open(QIODevice::WriteOnly | QIODevice::Text)) {
        emit errorOccurred(tr("无法保存文件: %1").arg(m_fileName));
        return false;
    }

    QTextStream stream(&file);
    stream.setCodec("UTF-8");
    stream << content;
    file.close();

    m_fileContent = content;
    m_originalData = content.toUtf8();
    m_fileModified = false;

    emit fileContentChanged();
    emit fileSaved(m_fileName);
    emit fileModifiedChanged();

    return true;
}

bool FileHandler::saveBinaryFile(const QVariantList &hexData)
{
    if (m_fileName.isEmpty()) {
        emit errorOccurred(tr("没有指定文件名"));
        return false;
    }

    QFile file(m_fileName);
    if (!file.open(QIODevice::WriteOnly)) {
        emit errorOccurred(tr("无法保存文件: %1").arg(m_fileName));
        return false;
    }

    // 将十六进制数据转换回二进制
    QByteArray binaryData;
    for (const QVariant &line : hexData) {
        QString hexLine = line.toString();
        QByteArray lineData = hexStringToByteArray(hexLine);
        binaryData.append(lineData);
    }

    file.write(binaryData);
    file.close();

    m_originalData = binaryData;
    m_fileModified = false;

    emit fileSaved(m_fileName);
    emit fileModifiedChanged();

    return true;
}

void FileHandler::closeFile()
{
    m_fileName.clear();
    m_isBinary = false;
    m_fileModified = false;
    m_originalData.clear();
    m_hexData.clear();
    m_fileContent.clear();

    emit fileNameChanged();
    emit isBinaryChanged();
    emit fileModifiedChanged();
    emit hexDataChanged();
    emit fileContentChanged();
    emit fileClosed();
}

bool FileHandler::isBinaryFile(const QString &filePath)
{
    QFileInfo fileInfo(filePath);
    QString extension = fileInfo.suffix().toLower();

    static const QStringList binaryExtensions = {
        "exe", "dll", "bin", "dat", "img", "so", "dylib",
        "jpg", "jpeg", "png", "gif", "bmp", "ico",
        "pdf", "doc", "docx", "xls", "xlsx",
        "zip", "rar", "7z", "tar", "gz"
    };

    return binaryExtensions.contains(extension);
}

void FileHandler::processBinaryData(const QByteArray &data)
{
    m_hexData.clear();

    // 预分配空间,提高性能
    int lineCount = (data.size() + 15) / 16; // 计算总行数
    m_hexData.reserve(lineCount);

    // 使用更高效的处理方式
    const uchar *bytes = reinterpret_cast<const uchar*>(data.constData());
    int dataSize = data.size();

    for (int i = 0; i < dataSize; i += 16) {
        QString hexLine;
        hexLine.reserve(48); // 预分配空间:16字节 * 3字符(2位十六进制+1空格)

        for (int j = 0; j < 16 && i + j < dataSize; j++) {
            uchar byte = bytes[i + j];

            // 构建十六进制字符串 - 修复的方法
            QString hexByte = QString("%1 ").arg(byte, 2, 16, QChar('0')).toUpper();
            hexLine.append(hexByte);
        }

        // 移除最后一个空格
        if (!hexLine.isEmpty() && hexLine.endsWith(' ')) {
            hexLine.chop(1);
        }

        // 创建行数据 - 只包含地址和十六进制数据
        QVariantMap lineData;
        lineData["address"] = QString("%1").arg(i, 8, 16, QChar('0')).toUpper();
        lineData["hex"] = hexLine;

        m_hexData.append(lineData);
    }

    emit hexDataChanged();
    emit fileOpened(m_fileName, true);
}

QByteArray FileHandler::hexStringToByteArray(const QString &hexString)
{
    QByteArray byteArray;
    QStringList hexBytes = hexString.split(' ', Qt::SkipEmptyParts);
    byteArray.reserve(hexBytes.size());

    for (const QString &hexByte : hexBytes) {
        bool ok;
        char byte = static_cast<char>(hexByte.toInt(&ok, 16));
        if (ok) {
            byteArray.append(byte);
        }
    }

    return byteArray;
}

main.qml文件源码

复制代码
import QtQuick 2.12
import QtQuick.Window 2.12
import QtQuick.Controls 2.12
import QtQuick.Dialogs 1.3
import QtQuick.Layouts 1.12
import FileEditor 1.0

ApplicationWindow {
    id: mainWindow
    width: 800
    height: 600
    title: "文件编辑器 - " + (fileHandler.fileName ? fileHandler.fileName : "未命名")
    visible: true

    FileHandler {
        id: fileHandler

        onFileOpened: {
            console.log("文件已打开:", fileName, "二进制:", isBinary)
            if (isBinary) {
                updateBinaryDisplay()
            } else {
                // 文本文件:直接将内容设置到 TextArea
                textArea.text = fileHandler.fileContent
            }
            mainWindow.title = "文件编辑器 - " + fileName
        }

        onFileContentChanged: {
            // 当文件内容变化时更新显示(对于文本文件)
            if (!fileHandler.isBinary && fileHandler.fileName) {
                textArea.text = fileHandler.fileContent
            }
        }

        onFileSaved: {
            console.log("文件已保存:", fileName)
            infoDialog.text = "文件已保存: " + fileName
            infoDialog.open()
        }

        onFileClosed: {
            console.log("文件已关闭")
            textArea.text = ""
            mainWindow.title = "文件编辑器 - 未命名"
        }

        onErrorOccurred: {
            console.error("错误:", errorMessage)
            errorDialog.text = errorMessage
            errorDialog.open()
        }

        onHexDataChanged: {
            if (fileHandler.isBinary) {
                updateBinaryDisplay()
            }
        }
    }

    // 更新二进制显示的函数
    function updateBinaryDisplay() {
        var displayText = ""
        for (var i = 0; i < fileHandler.hexData.length; i++) {
            var line = fileHandler.hexData[i]
            // 只显示地址和十六进制数据,移除 ASCII 部分
            displayText += line.address + "    " + line.hex + "\n"
        }
        textArea.text = displayText
    }

    // 菜单栏
    menuBar: MenuBar {
        Menu {
            title: "文件"

            MenuItem {
                text: "打开"
                onTriggered: openDialog.open()
            }

            MenuItem {
                text: "保存"
                onTriggered: {
                    if (fileHandler.isBinary) {
                        // 对于二进制文件,需要从显示的文本中提取十六进制数据
                        var lines = textArea.text.split('\n')
                        var hexData = []

                        for (var i = 0; i < lines.length; i++) {
                            if (lines[i].trim() === "") continue
                            var lineParts = lines[i].split('    ')
                            if (lineParts.length >= 2) {
                                hexData.push(lineParts[1].trim())
                            }
                        }

                        fileHandler.saveBinaryFile(hexData)
                    } else {
                        fileHandler.saveFile(textArea.text)
                    }
                }
            }

            MenuSeparator {}

            MenuItem {
                text: "关闭"
                onTriggered: fileHandler.closeFile()
            }

            MenuSeparator {}

            MenuItem {
                text: "退出"
                onTriggered: Qt.quit()
            }
        }

        Menu {
            title: "查看"

            MenuItem {
                text: "文本模式"
                enabled: fileHandler.fileName && fileHandler.isBinary
                onTriggered: {
                    // 重新以文本模式打开文件
                    var currentFile = fileHandler.fileName
                    fileHandler.closeFile()
                    fileHandler.openFile(currentFile)
                }
            }

            MenuItem {
                text: "十六进制模式"
                enabled: fileHandler.fileName && !fileHandler.isBinary
                onTriggered: {
                    // 重新以二进制模式打开文件
                    var currentFile = fileHandler.fileName
                    fileHandler.closeFile()
                    fileHandler.openFile(currentFile)
                }
            }
        }
    }

    // 主编辑区域
    ScrollView {
        anchors.fill: parent
        anchors.margins: 10

        TextArea {
            id: textArea
            width: parent.width
            height: parent.height
            font.family: fileHandler.isBinary ? "Courier New" : "Arial"
            font.pointSize: 10
            wrapMode: TextArea.Wrap
            selectByMouse: true
            placeholderText: "请打开一个文件开始编辑..."

            // 监听文本变化,用于设置修改状态
            onTextChanged: {
                if (fileHandler.fileName && !fileHandler.isBinary) {
                    // 可以在这里添加修改状态的逻辑
                }
            }
        }
    }

    // 状态栏
    footer: ToolBar {
        RowLayout {
            anchors.fill: parent
            Label {
                text: {
                    if (fileHandler.fileName) {
                        if (fileHandler.isBinary) {
                            return "十六进制模式 - " + fileHandler.fileName
                        } else {
                            return "文本模式 - " + fileHandler.fileName
                        }
                    } else {
                        return "就绪"
                    }
                }
                Layout.fillWidth: true
            }
            Label {
                text: "字符数: " + textArea.length
            }
        }
    }

    // 文件对话框
    FileDialog {
        id: openDialog
        title: "选择文件"
        selectMultiple: false
        nameFilters: ["所有文件 (*)"]
        onAccepted: {
            var filePath = openDialog.fileUrl.toString().replace("file:///", "")
            fileHandler.openFile(filePath)
        }
    }

    // 信息对话框
    MessageDialog {
        id: infoDialog
        title: "信息"
        icon: StandardIcon.Information
    }

    // 错误对话框
    MessageDialog {
        id: errorDialog
        title: "错误"
        icon: StandardIcon.Critical
    }

    // 键盘快捷键
    Shortcut {
        sequence: "Ctrl+O"
        onActivated: openDialog.open()
    }

    Shortcut {
        sequence: "Ctrl+S"
        onActivated: {
            if (fileHandler.isBinary) {
                var lines = textArea.text.split('\n')
                var hexData = []

                for (var i = 0; i < lines.length; i++) {
                    if (lines[i].trim() === "") continue
                    var lineParts = lines[i].split('    ')
                    if (lineParts.length >= 2) {
                        hexData.push(lineParts[1].trim())
                    }
                }

                fileHandler.saveBinaryFile(hexData)
            } else {
                fileHandler.saveFile(textArea.text)
            }
        }
    }

    Shortcut {
        sequence: "Ctrl+W"
        onActivated: fileHandler.closeFile()
    }
}

main.cpp文件源码

复制代码
#include <QGuiApplication>
#include <QQmlApplicationEngine>
#include <QQmlContext>
#include "filehandler.h"

int main(int argc, char *argv[])
{
    QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);

    QGuiApplication app(argc, argv);

    // 设置应用信息
    app.setApplicationName("文件编辑器");
    app.setApplicationVersion("1.0");
    app.setOrganizationName("MyCompany");

    // 注册 C++ 类型到 QML
    qmlRegisterType<FileHandler>("FileEditor", 1, 0, "FileHandler");

    QQmlApplicationEngine engine;

    // 加载 QML 文件
    const QUrl url(QStringLiteral("qrc:/main.qml"));

    QObject::connect(&engine, &QQmlApplicationEngine::objectCreated,
                     &app, [url](QObject *obj, const QUrl &objUrl) {
        if (!obj && url == objUrl)
            QCoreApplication::exit(-1);
    }, Qt::QueuedConnection);

    engine.load(url);

    return app.exec();
}

三、效果演示

打开二进制文件的效果,可以进行编辑保存。

相关推荐
-森屿安年-2 小时前
C++ 类与对象
开发语言·c++
ajassi20002 小时前
开源 C++ QT QML 开发(八)自定义控件--圆环
c++·qt·开源
深思慎考3 小时前
Linux二进制查看工具——hexdump
linux·c++·二进制·文件查看·hexdump
十重幻想3 小时前
PTA6-4 使用函数统计指定数字的个数(C)
c语言·c++·算法
铁手飞鹰3 小时前
VS2022创建项目工程笔记
c++·windows·笔记·visualstudio
ningbinzhang3 小时前
MFC 获取域名TXT记录内容
c++·mfc
佛系彭哥3 小时前
Win11下VSCode与MSYS2配置全攻略
c++·vscode·wxwidgets·msys2
Yupureki4 小时前
从零开始的C++学习生活 5:内存管理和模板初阶
c语言·c++·学习·visual studio
程序员Aries4 小时前
从零开始实现一个高并发内存池_DayThree:内存池整体框架与ThreadCache、TLS无锁访问
c++·学习·单例模式