南京专业的网站设计团队,做模板网站推荐乐云seo,网站开发西安中软,吉林网站建设代理渠道code review!
—— 杭州 2023-11-16 夜 文章目录 一.qt笔记之qml和C的交互#xff1a;官方文档阅读理解0.《Overview - QML and C Integration》中给出五种QML与C集成的方法1.Q_PROPERTY#xff1a;将C类的成员变量暴露给QML2.Q_INVOKABLE()或public slots#xff1a;将C类…code review!
—— 杭州 2023-11-16 夜 文章目录 一.qt笔记之qml和C的交互官方文档阅读理解0.《Overview - QML and C Integration》中给出五种QML与C集成的方法1.Q_PROPERTY将C类的成员变量暴露给QML2.Q_INVOKABLE()或public slots将C类的成员函数暴露给QML3.on\Signal\其中\Signal\第一个字母大写暴露C中的信号以及信号中传递的参数给QML 二.qt笔记之qml和C的交互笔记1.设置上下文属性(setContextProperty())1.1.fileio.h1.2.fileio.cpp1.3.main.cc1.4.main.qml 2.在QML引擎里面注册新类型(qmlRegisterType)2.1.fileio.h2.2.fileio.cpp2.3.main.cc2.4.main.qml 3.导出对应的QML扩展插件——略 一.qt笔记之qml和C的交互官方文档阅读理解
参考资料
官方文档《Exposing Attributes of C Types to QML》(将C类暴露给QML) 官方文档《Data Type Conversion Between QML and C》 官方文档《The Property System》 官方文档《Defining QML Types from C》(在QML中定义C类) 官方文档《Overview - QML and C Integration》
0.《Overview - QML and C Integration》中给出五种QML与C集成的方法
1.Exposing Attributes of C Classes to QML2.Defining QML Types from C3.Embedding C Objects into QML with Context Properties4.Interacting with QML Objects from C5.Data Type Conversion Between QML and C
1.Q_PROPERTY将C类的成员变量暴露给QML
Q_PROPERTY(…) This macro is used for declaring properties in classes that inherit QObject. Properties behave like class data members, but they have additional features accessible through the Meta-Object System. 翻译 这个宏用于在继承 QObject 的类中声明属性。属性的行为类似于类数据成员但通过元对象系统可以访问额外的功能。 翻译
为了与QML最大程度地互操作任何可写的属性都应该有一个关联的NOTIFY信号在属性值变化时发出。这允许该属性与属性绑定property binding一起使用属性绑定是QML的一个重要特性它通过在任何依赖项值变化时自动更新属性来强制属性之间的关系。
在上述示例中author属性的关联NOTIFY信号是authorChanged如Q_PROPERTY()宏调用中所指定的。这意味着每当信号被发出时——比如在Message::setAuthor()中当author发生变化时——它会通知QML引擎需要更新任何涉及author属性的绑定进而引擎将通过再次调用Message::author()来更新text属性。
如果author属性可写但没有关联的NOTIFY信号text值将使用Message::author()返回的初始值进行初始化但不会更新为此属性的任何后续更改。此外任何尝试从QML绑定到该属性的操作都会导致引擎产生运行时警告。
注意建议将NOTIFY信号命名为propertyChanged其中property是属性的名称。由QML引擎生成的关联属性更改信号处理程序的形式始终为onPropertyChanged而不管相关的C信号的名称如何因此建议信号名称遵循此约定以避免任何混淆。
GPT解读 在上述代码中Q_PROPERTY(QString author READ author WRITE setAuthor NOTIFY authorChanged) 声明了一个名为 author 的属性它具有读取方法 author() 和写入方法 setAuthor(const QString)。该属性还使用了信号 authorChanged()以便在属性值更改时发出通知。
setAuthor函数中修改了m_author的值后Q_PROPERTY声明的属性author的值也会相应地改变。这是因为在setAuthor函数中当m_author的值发生变化时通过emit authorChanged()语句发出了信号authorChanged()这个信号与Q_PROPERTY中的NOTIFY关键字相关联。
Q_PROPERTY的NOTIFY关键字用于指定一个信号当属性的值发生变化时会发出这个信号。在这种情况下authorChanged()信号与author属性相关联意味着当m_author的值发生变化时会发出authorChanged()信号。
因此当m_author的值在setAuthor函数中被修改时会发出authorChanged()信号这将导致与author属性相关联的代码例如绑定到该属性的UI元素能够接收到信号并相应地更新属性的值。
QString author() const 是 Message 类的成员函数用于读取私有成员变量 m_author 的值并返回。
QString m_author 是 Message 类的私有成员变量用于存储作者的名称。
在 main 函数中通过创建 Message 类的实例 msg将其设置为上下文属性使其可以在 QML 文件中访问。
在 MyItem.qml 中通过 msg.author 可以读取 Message 类中的 author 属性值。这将调用 Message::author() 方法。
在 Component.onCompleted 中将 msg.author 设置为 “Jonah”这将调用 Message::setAuthor() 方法并且在属性值更改后会发出 authorChanged() 信号。 2.Q_INVOKABLE()或public slots将C类的成员函数暴露给QML
Exposing Methods (Including Qt Slots):
3.onSignal其中Signal第一个字母大写暴露C中的信号以及信号中传递的参数给QML 翻译
任何继承自QObject类型的公共信号都可以在QML代码中访问。
QML引擎会自动为在QML中使用的任何继承自QObject类型的信号创建信号处理器。信号处理器的命名规则是on信号名其中信号名是信号的名称首字母大写。通过参数名可以在信号处理器中访问所有通过信号传递的参数。
例如假设MessageBoard类具有一个带有单个参数subject的newMessagePosted()信号
class MessageBoard : public QObject
{Q_OBJECT
public:// ...
signals:void newMessagePosted(const QString subject);
};如果MessageBoard类型已在QML类型系统中注册那么在QML中声明的MessageBoard对象可以通过名为onNewMessagePosted的信号处理器接收newMessagePosted()信号并检查subject参数的值
MessageBoard {onNewMessagePosted: (subject) console.log(New message received:, subject)
}二.qt笔记之qml和C的交互笔记
原文链接
QML进阶(八)实现QML界面与C类型交互
在QML工程中一般QML界面只负责前端交互而真正的业务逻辑都是C模块实现的。为了实现前端和后端的顺利衔接我们需要做好QML界面与C的交互。这里就介绍一下如何在QML中调用对应的C模块。在QML中调用C模块的方法主要有三种分别是:
1.设置上下文属性(setContextProperty()) 2.在QML引擎里面注册新类型(qmlRegisterType) 3.导出对应的QML扩展插件。
下面介绍一下三个方法的优缺点: 对于小型应用来说方法一设置上下文属性是最简单实用的方法。开发者只需要将对应的接口和变量暴露给QML就行。由于设置在QML中的变量是全局的一定要注意避免名称冲突。
在QML引擎里面注册新的类型允许用户在QML文件中控制C对象的生命周期这是设置上下文属性这种方法无法实现的。同时注册新类型的方法不会污染全局命名空间。但是这种方法也有一个缺点就是QML中的类型都需要提前注册所有用到的库都需要在程序启动的时候链接无法动态链接。但在绝大多数情况下这并不是一个问题。
QML扩展插件是弹性最好但也是最复杂的方法。QML允许用户在插件里面注册对应的新类型。这些新类型在QML第一次导入对应的符号的时候被加载。同时通过使用QML单例引入我们的新类型不会污染全局命名空间。由于新类型被插件化了我们可以很轻松的在多个项目中复用我们之前定义的新类型。
1.设置上下文属性(setContextProperty())
1.1.fileio.h 1.2.fileio.cpp 1.3.main.cc 1.4.main.qml 代码 fileio.h
#ifndef FILEIO_H
#define FILEIO_H#include QtCore
//用来打开的保存对应的文件
class FileIO : public QObject
{Q_OBJECT//定义QML可以访问的属性,定义格式如下//Q_PROPERTY(变量类型 访问名称 READ 读方法 WRITE 写方法 NOTIFY 发生变化的通知信号)//需要定义在Q_OBJECT之后第一个public之前Q_PROPERTY(QUrl source READ source WRITE setSource NOTIFY sourceChanged)Q_PROPERTY(QString text READ text WRITE setText NOTIFY textChanged)//ui_title是在QML使用的别名,m_title_content是对应的变量名称//CONSTANT说明是只读的Q_PROPERTY(QString ui_title MEMBER m_title_content CONSTANT)
public:FileIO(QObject *parent 0);~FileIO();//定义QML可以访问的方法Q_INVOKABLE void read();Q_INVOKABLE void write();QUrl source() const;QString text() const;
public slots:void setSource(QUrl source);void setText(QString text);
signals:void sourceChanged(QUrl arg);void textChanged(QString arg);
private:QUrl m_file_source;QString m_file_content;//用来测试的只读title数据QString m_title_content;
};#endif // FILEIO_Hfileio.cpp
#include fileio.h
FileIO::FileIO(QObject *parent): QObject(parent),m_title_content(QString(fileio))
{
}FileIO::~FileIO()
{
}void FileIO::read()
{if(m_file_source.isEmpty()) {return;}QFile file(m_file_source.toLocalFile());if(!file.exists()) {qWarning() Does not exits: m_file_source.toLocalFile();return;}if(file.open(QIODevice::ReadOnly)) {QTextStream stream(file);m_file_content stream.readAll();emit textChanged(m_file_content);}
}void FileIO::write()
{if(m_file_source.isEmpty()) {return;}QFile file(m_file_source.toLocalFile());if(file.open(QIODevice::WriteOnly)) {QTextStream stream(file);stream m_file_content;}
}QUrl FileIO::source() const
{return m_file_source;
}QString FileIO::text() const
{return m_file_content;
}void FileIO::setSource(QUrl source)
{if (m_file_source source)return;m_file_source source;emit sourceChanged(source);
}void FileIO::setText(QString text)
{if (m_file_content text)return;m_file_content text;emit textChanged(text);
}main.cc
#include QGuiApplication
#include QQmlApplicationEngine
#include QQmlContext
#include QFont
#include fileio.h
int main(int argc, char *argv[])
{QGuiApplication app(argc, argv);//根据不同的QT版本设置对应的编码app.setFont(QFont(Microsoft Yahei, 9));
#if (QT_VERSION QT_VERSION_CHECK(5,0,0))
#if _MSC_VERQTextCodec *codec QTextCodec::codecForName(gbk);
#elseQTextCodec *codec QTextCodec::codecForName(utf-8);
#endifQTextCodec::setCodecForLocale(codec);QTextCodec::setCodecForCStrings(codec);QTextCodec::setCodecForTr(codec);
#elseQTextCodec *codec QTextCodec::codecForName(utf-8);QTextCodec::setCodecForLocale(codec);
#endif//定义对应的类型指针QScopedPointerFileIO current_file_io(new FileIO());QQmlApplicationEngine engine;//在加载对应的URL之前, 设置上下文属性engine.rootContext()-setContextProperty(qmlfileio,current_file_io.data());engine.load(QUrl(QStringLiteral(qrc:/main.qml)));if (engine.rootObjects().isEmpty())return -1;return app.exec();
}main.qml
import QtQuick 2.8
import QtQuick.Window 2.2
import Qt.labs.platform 1.0Window {visible: truewidth: 440height: 300title: qsTr(Context fileIO)Column{Rectangle{id:contentRectx:10; y:10width: 400height: 150//用于显示打开的文本文件的内容Text{ id:contentanchors.top :contentRect.topanchors.bottom: contentRect.bottomanchors.left: contentRect.leftanchors.right: contentRect.righttext: qmlfileio.text}border.color: #CCCCCC}//点击的按钮用来选择对应的文件Rectangle{anchors.horizontalCenter:contentRect.horizontalCentercolor: #4D9CF8width:200height: 30Text{anchors.centerIn: parenttext:点击打开文件}MouseArea {anchors.fill: parentonClicked: {fileDialog.open();}}}}//文件选择窗口,选择需要打开的文件//并读取文件中对应的内容FileDialog{id: fileDialogfolder: StandardPaths.standardLocations(StandardPaths.PicturesLocation)[0]onFileChanged: {qmlfileio.source fileDialog.file;qmlfileio.read();}}
}2.在QML引擎里面注册新类型(qmlRegisterType)
2.1.fileio.h 2.2.fileio.cpp 2.3.main.cc 2.4.main.qml 代码 fileio.h
#ifndef FILEIO_H
#define FILEIO_H#include QtCore
//用来打开的保存对应的文件
class FileIO : public QObject
{Q_OBJECT//定义QML可以访问的属性,定义格式如下//Q_PROPERTY(变量类型 访问名称 READ 读方法 WRITE 写方法 NOTIFY 发生变化的通知信号)//需要定义在Q_OBJECT之后第一个public之前Q_PROPERTY(QUrl source READ source WRITE setSource NOTIFY sourceChanged)Q_PROPERTY(QString text READ text WRITE setText NOTIFY textChanged)//ui_title是在QML使用的别名,m_title_content是对应的变量名称//CONSTANT说明是只读的Q_PROPERTY(QString ui_title MEMBER m_title_content CONSTANT)
public:FileIO(QObject *parent 0);~FileIO();//定义QML可以访问的方法Q_INVOKABLE void read();Q_INVOKABLE void write();QUrl source() const;QString text() const;
public slots:void setSource(QUrl source);void setText(QString text);
signals:void sourceChanged(QUrl arg);void textChanged(QString arg);
private:QUrl m_file_source;QString m_file_content;//用来测试的只读title数据QString m_title_content;
};#endif // FILEIO_Hfileio.cpp
#include fileio.h
FileIO::FileIO(QObject *parent): QObject(parent),m_title_content(QString(fileio))
{
}FileIO::~FileIO()
{
}void FileIO::read()
{if(m_file_source.isEmpty()) {return;}QFile file(m_file_source.toLocalFile());if(!file.exists()) {qWarning() Does not exits: m_file_source.toLocalFile();return;}if(file.open(QIODevice::ReadOnly)) {QTextStream stream(file);m_file_content stream.readAll();emit textChanged(m_file_content);}
}void FileIO::write()
{if(m_file_source.isEmpty()) {return;}QFile file(m_file_source.toLocalFile());if(file.open(QIODevice::WriteOnly)) {QTextStream stream(file);stream m_file_content;}
}QUrl FileIO::source() const
{return m_file_source;
}QString FileIO::text() const
{return m_file_content;
}void FileIO::setSource(QUrl source)
{if (m_file_source source)return;m_file_source source;emit sourceChanged(source);
}void FileIO::setText(QString text)
{if (m_file_content text)return;m_file_content text;emit textChanged(text);
}main.cc
#include QGuiApplication
#include QQmlApplicationEngine
#include QQmlContext
#include QFont
#include fileio.h
int main(int argc, char *argv[])
{QGuiApplication app(argc, argv);//在engine声明之前注册C类型//1:类在qml中别名 2:版本主版本号 3:版本的次版本号 4类的名称qmlRegisterTypeFileIO(org.fileio,1,0,FileIO);QQmlApplicationEngine engine;engine.load(QUrl(QStringLiteral(qrc:/main.qml)));if (engine.rootObjects().isEmpty())return -1;return app.exec();
}main.qmlimport org.fileio 1.0
import QtQuick 2.8
import QtQuick.Window 2.2
import Qt.labs.platform 1.0
import org.fileio 1.0Window {visible: truewidth: 440height: 300title: qsTr(Context fileIO)Column{Rectangle{id:contentRectx:10; y:10width: 400height: 150//用于显示打开的文本文件的内容Text{ id:contentanchors.top :contentRect.topanchors.bottom: contentRect.bottomanchors.left: contentRect.leftanchors.right: contentRect.righttext: fileIO.text}border.color: #CCCCCC}//点击的按钮用来选择对应的文件Rectangle{anchors.horizontalCenter:contentRect.horizontalCentercolor: #4D9CF8width:200height: 30Text{anchors.centerIn: parenttext:点击打开文件}//点击按钮弹出选择文件的对话框MouseArea {anchors.fill: parentonClicked: {fileDialog.open();}}}}//文件选择窗口,选择需要打开的文件//并读取文件中对应的内容FileDialog{id: fileDialogfolder: StandardPaths.standardLocations(StandardPaths.PicturesLocation)[0]onFileChanged: {fileIO.source fileDialog.file;fileIO.read();}}//外部导入的C类型可以直接定义使用//外部通过ID来访问该模块FileIO{id:fileIO}
}3.导出对应的QML扩展插件——略