Qt Quick读取本地文件并显示成表格

13 篇文章 5 订阅

🚀作者:CAccept
🎂专栏:Qt Quick
在这里插入图片描述

🍎C++代码部分实现

C++代码部分负责读取本地的文本文件,通过规则将文件进行解析,然后再通过信号与槽机制将数据传递给QML中供其使用,现在让我们来看看思路吧。
实现思路:
1、在QML中实现QML的信号和FileLoad槽方法的绑定
2、QML触发信号并将文件路径传递给FileLoad
3、一行一行解析数据
4、每次解析完一行数据就将一行数据利用信号传给QML,用于添加表格数据



fileload.h

#ifndef FILELOAD_H
#define FILELOAD_H

#include <QObject>
#include <QString>
#include <QUrl>
#include <QFile>
#include <QTextStream>
#include <QMessageBox>
class FileLoad : public QObject
{
    Q_OBJECT
public:
    explicit FileLoad(QObject *parent = nullptr);
    //解析一行数据
    void parseLineData(QString line);
signals:
	//由于文件有9列所以就搞了9个参数,来传递数据
    void sendFileData(QString p1,QString p2,QString p3,QString p4,QString p5,QString p6,QString p7,QString p8,QString p9);
public slots:
	//读取整体文件
    void fileRead(QString fileName);

};

#endif // FILELOAD_H

fileload.cpp

#include "fileload.h"
#include <QDebug>
FileLoad::FileLoad(QObject *parent) : QObject(parent)
{

}

void FileLoad::parseLineData(QString line)
{
    //将line前面的空格进行去除
    line.remove (QRegExp ("^ +\s*"));
    //以四个空格为分隔符进行分割
    QStringList list = line.split("   ");
    QStringList data;
    int count = 0;
    for(auto parameter:list){
    	//去除字符串两边的空格
        parameter = parameter.simplified();
        count++;
        data.push_back(parameter);
    }
    for(int i=0;i<count;i++)
    {
        qDebug()<<data[i];
    }
    if(count == 9)
    {
    	//发送信号
        emit sendFileData(data[0],data[1],data[2],data[3],data[4],data[5],data[6],data[7],data[8]);
    }
}

void FileLoad::fileRead(QString fileName)
{
    //qDebug()<<"开始fileRead!"<<endl;
    QFile f(fileName);
    if (!f.open(QIODevice::ReadOnly|QIODevice::Text))//打开指定文件
    {
        qDebug()<<"没有找到文件!!";
        return;
    }

    QTextStream txtInput(&f);
    QString lineStr;
    while (!txtInput.atEnd())
    {
        lineStr = txtInput.readLine();  //读取数据
		//解析这一行的数据
        parseLineData(lineStr);
    }

    f.close();
}


🚀C++类注册到QML中

注册过程:
1、main.cpp包含头文件fileload.h
2、创建FileLoad对象
3、engine.rootContext()->setContextProperty对FileLoad对象进行注册
main.cpp

#include <QGuiApplication>
#include <QQmlApplicationEngine>
#include <QQmlContext>
#include <QDir>
#include <QApplication>
#include <QQmlContext>
#include <fileload.h>
int main(int argc, char *argv[])
{
    QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);

    QApplication app(argc, argv);
    QString path = QCoreApplication::applicationDirPath();
    //创建FileLoad对象
    FileLoad fileload;
    QQmlApplicationEngine engine;
    //将path传递进去,方便调用路径查找文件
    engine.rootContext()->setContextProperty("appDir",path);
    engine.rootContext()->setContextProperty("fileload", &fileload);
    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();
}

🎂QML部分实现

QML部分的实现关键点在👇
1、定义信号

signal qmlGetData(string p1, string p2, string p3,string p4, string p5, string p6,string p7, string p8, string p9)
//将地址送给fileload,让fileload解析
signal qmlFilePathAccepted(string filename)

2、将QML定义的信号与C++类对象fileload的槽方法进行连接

//将qmlFilePathAccepted和fileload的槽方法fileRead进行连接
qmlFilePathAccepted.connect(fileload.fileRead)

3、将C++类对象fileload的信号实现对应的槽方法

//绑定信号槽
Connections{
    target: fileload
    //实现fileload中sendFileData信号对应的槽方法
    function onSendFileData(p1,p2,p3,p4,p5,p6,p7,p8,p9)
    {
    	//发射信号
        qmlGetData(p1,p2,p3,p4,p5,p6,p7,p8,p9)
    }
}

4、实现qmlGetData对应响应的槽方法

onQmlGetData:
{
	 //给model后面追加数据
     listModel.append({"p1":p1,"p2":p2,"p3":p3,"p4":p4,"p5":p5,"p6":p6,"p7":p7,"p8":p8,"p9":p9})
}

5、实现表格的显示

main.qml

import QtQuick 2.6
import QtQuick.Window 2.2
import QtQuick.Layouts 1.2
import QtQuick.Controls 1.4
import QtQuick.Controls.Styles 1.2

Window {
    id:gridArea
    width: 1050;
    height: 457
    visible: true
    signal qmlGetData(string p1, string p2, string p3,string p4, string p5, string p6,string p7, string p8, string p9)
    signal qmlFilePathAccepted(string filename)
    onQmlGetData:
    {
        console.log("触发qmlGetData")
        listModel.append({"p1":p1,"p2":p2,"p3":p3,"p4":p4,"p5":p5,"p6":p6,"p7":p7,"p8":p8,"p9":p9})
    }

    TableView {
        id: tableView
        objectName: "tableView"
        anchors.fill: parent

        TableViewColumn {
            id: p1
            title: "p1"
            role: "p1"
            width:60

        }
        TableViewColumn {
            id: p2
            title: "p2"
            role: "p2"
            width:60
        }
        TableViewColumn {
            id: p3
            title: "p3"
            role: "p3"
            width:60
        }
        TableViewColumn {
            id: p4
            title: "p4"
            role: "p4"
            width:60

        }
        TableViewColumn {
            id: p5
            title: "p5"
            role: "p5"
            width:60

        }
        TableViewColumn {
            id: p6
            title: "p6"
            role: "p6"
            width:60

        }
        TableViewColumn {
            id: p7
            title: "p7"
            role: "p7"
            width:60

        }
        TableViewColumn {
            id: p8
            title: "p8"
            role: "p8"
            width:60

        }
        TableViewColumn {
            id: p9
            title: "p9"
            role: "p9"
            width:60

        }

        model: ListModel {
            id: listModel
            objectName: "listModel"

        }
    }
    //绑定信号槽
    Connections{
        target: fileload
        //实现fileload中sendFileData信号对应的槽方法
        function onSendFileData(p1,p2,p3,p4,p5,p6,p7,p8,p9)
        {
            qmlGetData(p1,p2,p3,p4,p5,p6,p7,p8,p9)
        }
    }

    Component.onCompleted: {
    	//将qmlFilePathAccepted和fileload的槽方法fileRead进行连接
        qmlFilePathAccepted.connect(fileload.fileRead)
        //将传进行来的appDir运行路径进行组合这样更好,且移植性强
        qmlFilePathAccepted(appDir+"/inpparameter.DAT")
    }
}

我的文件👇
在这里插入图片描述

运行效果👇
在这里插入图片描述


🌰小知识点

⭐C++与QML进行交互

将C++类注册到QML中一般有两种方法
1、qmlRegisterType函数

int qmlRegisterType(const char *uri, int versionMajor, int versionMinor, const char *qmlName);

第一个参数uri指的是QML中import后的内容,相当于头文件名,第二个第三个参数分别是主次版本号,第四个指的是QML中类的名字(第四个QML的类名首字母一定要大写,要不然会报错)。<>中放的是C++的类的名字

qmlRegisterType则用于向QML引擎注册一个新的类型,该类型可以在QML代码中直接创建。这种方法适用于需要在QML中创建新对象或自定义组件时使用。通过qmlRegisterType函数注册后,我们就可以在QML代码中像使用其他标准类型一样使用该类型了。

//在main.cpp中使用👇
qmlRegisterType<qan::RightResizer>("QuickQanava", 2, 0, "RightResizer");
//那么我们在qml文件中就要👇
import QuickQanava 2.0 as Qan
Qan.RightResizer{
   balabala
   ..... 
   ....
}

2、engine->rootContext()->setContextProperty

engine.rootContext()->setContextProperty用于将一个现有的C++对象实例暴露给QML引擎。这种方法适合于简单的场景,例如在QML中调用C++对象中的方法或访问其属性等。我们可以使用以下代码将C++对象实例暴露给QML引擎:

// C++对象
MyObject myObject;
// 将myObject暴露给QML引擎,这样就可以在QML文件中使用myObject来控制和使用我们外面定义的C++对象myObject
engine.rootContext()->setContextProperty("myObject", &myObject);

engine->rootContext()->setContextProperty更适用于一些简单的场景不需要多次创建,整个过程就只要存在一个这个对象就可以,而qmlRegisterType就相当于创建了一个新的类型,可以反复给QML创建


⭐将运行路径进行传递保证程序的稳定性

可以通过Qt的API得到当前程序的执行路径,然后通过注册将路径传递给QML使用,这样就可以在一定程度上保证程序的可移植性👇
main.cpp

QString path = QCoreApplication::applicationDirPath();
engine.rootContext()->setContextProperty("appDir",path);

在qml中就可以这样使用👇

qmlFilePathAccepted(appDir+"/inpparameter.DAT")

⭐QML中定义信号其默认的槽方法是on+大写信号名

signal qmlGetData(string p1, string p2, string p3,string p4, string p5, string p6,string p7, string p8, string p9)
onQmlGetData:
{
   listModel.append({"p1":p1,"p2":p2,"p3":p3,"p4":p4,"p5":p5,"p6":p6,"p7":p7,"p8":p8,"p9":p9})
}

感谢您看完了这篇文章,希望这篇文章对您有所帮助,当然,如果在这篇文章中有遇到一些问题或者疑问的话请一定在评论区中提出万分感谢!!
在这里插入图片描述

  • 2
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值