说实话,想学QML很久了,而且也发起了好几次进攻,然后就不了了之了。这次我希望我可以学会这门语言,移动端也可以耍耍了。
我是跟着书《Qt+Quick核心编程》一点点学的,书的前面章节都比较简单,就是介绍一些控件的用法、布局的使用、事件的用法等,都比较简单,唯一觉得不好的是:没有了按F1的快捷帮助,而且在写ECMAScript时,有写方法没有补全的功能,纯手打很难受。
所以就想能用自己顺手的QWidgets和QML结合起来吗?答案是肯定的,毕竟都是Qt出品,自己的东西肯定要支持。不过这里,先简单调用继承QObject的自定义类。
先说明一下QML这门语言:对ECMAScript的扩展,并融合了Qt的元对象系统。而QtWidgets也是在元对象系统的操纵下,这样的特性就使得QML很容易从C++中得到扩展,在一定的条件下,QML就可以访问QObject派生类的成员,例如信号、槽函数、枚举类型、属性、成员函数等。
上面说法太专业?那么换个思维,看下项目下的main.cpp文件,是不是对QML和c++的混合编程一点也不怀疑了?毕竟用c++语言加载的qml文件。
还有疑问是不是“在一定的条件下,QML就可以访问QObject派生类的成员,例如信号、槽函数、枚举类型、属性、成员函数等。”这句话?
“一定条件”需要两点:一是从QObject或者QObject的派生类继承,二呢,使用Q_OBJECT宏
“信号和槽函数”平时怎么写,现在就怎么写,因为它本身实现就是依赖的元对象系统的,它的实现条件就是上面的条件
“枚举类型”需要将这个枚举类型注册到元对象系统,通过宏Q_ENUMS
“属性”同样,用宏Q_PROPERTY注册,具体用法可参考亮大博客
“成员函数”需要在函数的声明前加 Q_INVOKABLE
想了想,还是附加一个.h文件,看着更直观一点:
#ifndef COLORMAKER_H
#define COLORMAKER_H
#include
#include
#include
class ColorMaker :public QObject
{
Q_OBJECT
Q_ENUMS(GenerateAlgorithm)
Q_PROPERTY(QColor color READ color WRITE setColor NOTIFY colorChanged)
Q_PROPERTY(QColor timeColor READ timeColor)
public:
ColorMaker(QObject* parent=0);
~ColorMaker();
enum GenerateAlgorithm{
RandomRGB,
RandomRed,
RandomGreen,
RandomBlue,
LinearIncrease
};
QColor color()const;
void setColor(const QColor& color);
QColor timeColor() const;
Q_INVOKABLE GenerateAlgorithm algorithm() const;
Q_INVOKABLE void setAlgorithm(GenerateAlgorithm algorithm);
signals:
void colorChanged(const QColor& color);
void currentTime(const QString& strTime);
public slots:
void start();
void stop();
protected:
void timerEvent(QTimerEvent* event);
private:
GenerateAlgorithm m_algorithm;
QColor m_currentColor;
int m_nColorTimer;
};
#endif // COLORMAKER_H
上面说明了C++类应该具备的一些条件,那么qml该怎么调用c++类呢,重点来喽!有两种方法:
1> c++实现一个类,qmlRegisterType注册为QML的类型,然后在qml文件以此类型创建对象。这种调用方法我是比较喜欢的,代码看着更清晰明了。(ColorMaker为我c++的类,此代码参考安总的书中代码)
main.cpp文件
int main(int argc, char *argv[])
{
QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
QGuiApplication app(argc, argv);
qmlRegisterType("an.qt.ColorMaker",1,0,"ColorMaker");
QQuickView viewer;
viewer.setResizeMode(QQuickView::SizeRootObjectToView);
viewer.setSource(QUrl("qrc:///main.qml"));
QObject::connect(viewer.engine(),&QQmlEngine::quit,&app,&QGuiApplication::quit);
viewer.show();
return app.exec();
}
main.qml文件
//文件先导入c++类型
import an.qt.ColorMaker 1.0
//以下是在Rectangle体内的创建的C++类的对象 color属性是在C++类中Q_PROPERTY注册过的属性
ColorMaker{
id:colorMaker;
color: Qt.green;
}
2> 将c++类对象作为qml的属性,安总中new出的对象,我不建议new,因为还得找时机delete,这个就很麻烦了:qml又不像c++有析构函数,那么就需要在退出时删除,close事件或quit时,都要写删除操作;然后我发现close事件又要重写QQuickView 的Close事件。
此种方法将c++类对象设为属性后,在qml中直接访问,但是这就导致枚举类型(如ColorMaker::RandomRGB)无法访问了。
main.cpp文件
int main(int argc, char *argv[])
{
QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
QGuiApplication app(argc, argv);
QQuickView viewer;
ColorMaker colorMaker;
viewer.setResizeMode(QQuickView::SizeRootObjectToView);
//此处将colorMaker设为qml全局属性
viewer.rootContext()->setContextProperty("colorMaker",&colorMaker);
viewer.setSource(QUrl("qrc:///main.qml"));
QObject::connect(viewer.engine(),&QQmlEngine::quit,&app,&QGuiApplication::quit);
viewer.show();
return app.exec();
}
qml文件
//无需创建对象,直接使用,如此处按钮直接调用的colorMaker的开始功能
Button{
id:start;
text: "start";
anchors.left: parent.left;
anchors.leftMargin: 4;
anchors.bottom: parent.bottom;
anchors.bottomMargin: 4;
onClicked: {
colorMaker.start();
}
}
源代码我就不提供了,想要的去找安总代码,或者留言告诉我,我再上传。
要说的都已经说了,最后给自己加个油:奥利给!!