先上视频效果:
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 ---------------------------------------------------------------------------------------------------------------------- 我们尊重原创,也注重分享,文章来源于微信公众号:你才小学生,建议关注公众号查看原文。如若侵权请联系qter@qter.org。 ----------------------------------------------------------------------------------------------------------------------
|