前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >QML动态显示组件(支持在线编辑动态刷新)

QML动态显示组件(支持在线编辑动态刷新)

作者头像
Qt君
发布2019-07-15 15:20:51
5.1K0
发布2019-07-15 15:20:51
举报

先上视频效果:

QML动态组件显示器主要用于方便界面开发,在线编辑保存后自动刷新组件界面,并支持拖拽文件显示的方式。

QML部分代码:

import QtQuick 2.6
import MonitorAndControlFile 1.0
import QtQuick.Window 2.0

Window {
    id: root

    property variant qmlObjects: []

    visible: true
    width: 320*1.5
    height: 240*1.5
    title: qsTr("QML组件动态显示器v0.3")

    Column {
        Item {
            width: root.width; height: root.height - background.height
            Column {
                anchors.centerIn: parent
                spacing: 10

                Text {
                    anchors.horizontalCenter: parent.horizontalCenter
                    font.pixelSize: 24
                    color: "gray"
                    text: "将QML文件拖到这里显示"
                }

                Text {
                    anchors.horizontalCenter: parent.horizontalCenter
                    font.pixelSize: 24
                    color: "gray"
                    text: "修改QML文件实时动态刷新"
                }
            }
        }

        Image {
            id: background
            anchors.horizontalCenter: parent.horizontalCenter
            width: root.width*0.8; height: width*800/2800
            source: "qrc:/Other/xiaoxuesheng.jpg"
        }
    }

    MonitorAndControlFile {
        id: monitorAndControlFile
        onStatusChanged: load(url)
    }

    DropArea {
        anchors.fill: parent
        onDropped: monitorAndControlFile.url = (drop.text.replace(/[\r\n]/g,""))
    }

    function load(url) {
        monitorAndControlFile.clear()

        for (var i = 0; i < qmlObjects.length; i++) {
            var obj = qmlObjects[i]
            /* 开启这两个只能显示一个组件 */
//            obj.visible = false 
//            console.log(obj)
        }

        console.log("Load: ", url)

        try {
            var component = Qt.createComponent(url);
        } catch(err) {
            console.log('Error on line ' + err.qmlErrors[0].lineNumber + '\n' + err.qmlErrors[0].message);
        }

        if (component.status == Component.Error) {
            console.log("Error loading component:", component.errorString());
            return null;
        }

        if (component.status == Component.Ready) {
            var object = component.createObject(root);
            object.visible = true
            qmlObjects.push(object)
        }
    }
}

C++部分代码:

#include "MonitorAndControlFile.h"

#include <QFileInfo>
#include <QDebug>

void MonitorAndControlFile::clear()
{
    m_engine->trimComponentCache();
    m_engine->clearComponentCache();
}

MonitorAndControlFile::MonitorAndControlFile(QObject *parent) : QObject(parent)
{
    connect(&m_fileWatch, SIGNAL(fileChanged(QString)), this, SLOT(onFileChanged(QString)));
    m_engine = qmlEngine();
}

MonitorAndControlFile::~MonitorAndControlFile()
{
}

QString MonitorAndControlFile::url()
{
    return m_url;
}

void MonitorAndControlFile::setUrl(QString url)
{
    QString file = url;
#ifdef Q_OS_WIN
    QFileInfo fileInfo(file.remove("file:///"));
#endif

#ifdef Q_OS_UNIX
    QFileInfo fileInfo(file.remove("file://"));
#endif

    if (fileInfo.isFile()) {
        m_fileWatch.addPath(file);
        if (!m_monitorFiles.contains(file))
            m_monitorFiles.append(file);

        m_url = url;
        emit statusChanged();
    }
}

void MonitorAndControlFile::onFileChanged(QString file)
{
    foreach(QString file, m_monitorFiles) {
        m_fileWatch.addPath(file);
    }
    qDebug()<<"Watch file: "<<m_fileWatch.files();
    emit statusChanged();
}

实现原理:

1. QML端实现方式主要是拖拽方式的实现与QML组件的动态加载显示;

拖拽实现获取QML组件:

DropArea { 
        anchors.fill: parent
        onDropped: monitorAndControlFile.url = (drop.text.replace(/[\r\n]/g,""))
    }

QML动态加载:

try {
            var component = Qt.createComponent(url);
        } catch(err) {
            console.log('Error on line ' + err.qmlErrors[0].lineNumber + '\n' + err.qmlErrors[0].message);
        }

2. C++端主要实现的是监控文件的变化,进而动态加载QML组件;

clear函数主要用于更新组件需要清除上一个组件的资源,不然不能更新到组件刷新。

void MonitorAndControlFile::clear()
{
    m_engine->trimComponentCache();
    m_engine->clearComponentCache();
}

MonitorAndControlFile类构造函数用于绑定文件监控

MonitorAndControlFile::MonitorAndControlFile(QObject *parent) : QObject(parent)
{
    connect(&m_fileWatch, SIGNAL(fileChanged(QString)), this, SLOT(onFileChanged(QString)));
    m_engine = qmlEngine();
}

3. MonitorAndControlFile类qmlRegisterType注册到QML中通过import导入使用;

qmlRegisterType<MonitorAndControlFile>("MonitorAndControlFile", 1, 0, "MonitorAndControlFile");
import MonitorAndControlFile 1.0

程序的一些小细节:

(1) 由于QML获取到的文件路径有可能附带换行符导致文件不能识别,所以需要移除多余的换行符;

drop.text.replace(/[\r\n]/g,"")

(2) 由于操作系统不一样导致到Windows系统与Linux系统的文件读取方式也不一样。这里用到了系统宏判断移除多余的前缀。

Windows系统获取文件方式:
"file:///C:/Users/Strong/Documents/workspace/DisplayQtComponent/Other/Text-1.qml"
Linux系统获取文件方式: 
"file:///Users/Strong/Documents/workspace/DisplayQtComponent/Other/Text-1.qml"
#ifdef Q_OS_WIN
    QFileInfo fileInfo(file.remove("file:///"));
#endif

#ifdef Q_OS_UNIX
    QFileInfo fileInfo(file.remove("file://"));
#endif

代码地址(不定时更新):

https://github.com/aeagean/DisplayQtComponent
本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2018-11-25,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 Qt君 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档