QML programming-learn Qt development

QML programming-learn Qt development

Author: Old 9.Technology

Social: Zhihu

Public number: Laojiu School (the newcomers have surprises)

Special statement: originality is not easy, no reprinting or plagiarism is allowed without authorization, if you need to reprint, please contact the author for authorization

Preface

The code of this handout is executed using Qt 6 version, please rest assured to use it.

What is QML

Let me refer to the translation:

QML is an acronym for Qt Meta-object Language. It is a declarative programming language, and it is an integral part of the Qt framework. The main function of QML is to allow developers to quickly and easily develop user interfaces. These interfaces include desktop applications, mobile devices, and embedded interfaces. In addition, QML can be seamlessly integrated with JavaScript for development and use, that is, JavaScript files can be used directly in QML code.

The first Hello World

import QtQuick 2.9 import QtQuick.Window 2.2 Window{ visible : true width : 640 height : 480 title :qsTr( "Hell World" ); Rectangle { width : 360 height : 360 Rectangle{ id : button1 width : 100 height : 30 color : "red" radius : 5 anchors.centerIn:parent Text{ id : buttonText text :qsTr( "Button" ) color : "white" anchors.centerIn:parent } MouseArea{ anchors.fill:parent onClicked :{ buttonText.text = qsTr( "Clicked" ); buttonText.color = "black" ; } } } } Text{ id :text1 text : qsTr( "Hello World" ) anchors.left:button1.right } Image{ source : "nb.png" anchors.centerIn:parent } } Copy code

running result

Mouse event response

import QtQuick 2.9 import QtQuick.Window 2.2 Window{ visible : true width : 480 height : 240 Rectangle{ anchors.fill:parent color : "#4b7a4a" MouseArea{ anchors.fill:parent acceptedButtons : Qt.AllButtons onClicked :{ console .log( "Mouse Clicked." ) console .log( "Mouse Location: <" ,mouseX, "," ,mouseY, ">" ). if (mouse.button === Qt.RightButton) parent.color = 'blue' if (mouse.button === Qt.LeftButton) parent.color = 'red' if (mouse.button === Qt.MiddleButton) parent.color = 'yellow' } onReleased : { //print to console console .log( "Mouse Released." ) } onDoubleClicked : { //print to console console .log( "Mouse Double Clicked." ) } } } } Copy code

running result

Animation

Demo code

import QtQuick 2.9 import QtQuick.Window 2.2 Window{ visible : true width : 400 height : 640 Rectangle{ id : rect anchors.centerIn: parent height : 100 width : 100 color : "blue" MouseArea{ anchors.fill: parent onClicked : na.running = true } NumberAnimation { id : na //ID of the animation type target : rect //The target item of the animation run property : "height" //What is the attribute of the animation modification target item duration : 200 //The length of the animation execution time from : rect.height //The initial value of the animation attribute to : 200 //The final value of the attribute after the animation is executed } } } Copy code

running result

After we click on the blue square

Create custom elements in C++

QML has a large number of visual elements. If you only use the QML scripting language, you can also build complex applications with the visual elements of QML. We can build interfaces based on these standard parts. In addition, we can also use Canvas to create custom elements. Except that touch elements cannot be constructed, other interface elements of QML can be constructed.

However, QML scripts are not a panacea. Although QML uses OpenGL technology to achieve high-speed interface drawing, we can use QML to implement two custom drawing elements:

  • The traditional for Qt way using QPainter (QQuickPaintedItem). (The traditional way is to use QPainter/QQuickPaintedItem to draw the interface)
  • The common QML way using QQuickItem and OpenGL functionality. (QML generally uses QQuickItem and OpenGL functions to draw the interface)

The first method seems to be easier to implement, and the efficiency of QtQuick drawing is relatively slow, so if we use the second method to draw interface elements, they will run faster.

Demo code

QQuickCustomItem header file

# pragma once # include <QQuickItem> /** * Function: Create a custom class to implement the QQuickItem class. Used to demonstrate the implementation of custom control elements * Author: Technology Big Millet */ class QQuickCustomItem : public QQuickItem { Q_OBJECT Q_PROPERTY (QColor color READ color WRITE setColor NOTIFY colorChanged) public : QQuickCustomItem(QQuickItem* parent = Q_NULLPTR); void paint (QPainter* painter) ; protected : QSGNode* updatePaintNode (QSGNode* oldNode, UpdatePaintNodeData* updatePaintNodeData) ; QColor color () const ; void setColor ( const QColor& color) ; private : QColor m_color; bool m_needUpdate; signals: void colorChanged () ; }; Copy code

QQuickCustomItem source file

# include "QQuickCustomItem.h" # include <QSGGeometryNode> # include <QSGFlatColorMaterial> # include <QPainterPath> # include <QPainter> QQuickCustomItem:: QQuickCustomItem (QQuickItem* parent /*= Q_NULLPTR*/ ) : QQuickItem (parent), m_color (Qt::red), m_needUpdate ( true ) { setFlag (QQuickItem::ItemHasContents); } void QQuickCustomItem::paint (QPainter* painter) { QPainterPath path; path. moveTo ( width ()/ 2 , 0 ); path. lineTo ( width (), height ()); path. lineTo ( 0 , height ()); path. lineTo ( width ()/2 , 0 ); painter-> fillPath (path, m_color); } QSGNode* QQuickCustomItem::updatePaintNode (QSGNode* oldNode, UpdatePaintNodeData* updatePaintNodeData) { Q_UNUSED (updatePaintNodeData) QSGGeometryNode* root = static_cast <QSGGeometryNode*>(oldNode); if (!root) { root = new QSGGeometryNode; QSGGeometry* geometry = new QSGGeometry (QSGGeometry:: defaultAttributes_Point2D (), 3 ); geometry-> setDrawingMode ( 6 ); geometry-> vertexDataAsPoint2D ()[ 0 ]. set ( width ()/2 , 0 ); geometry-> vertexDataAsPoint2D ()[ 1 ]. set ( width (), height ()); geometry-> vertexDataAsPoint2D ()[ 2 ]. set ( 0 , height ()); root-> setGeometry (geometry); root-> setFlag (QSGNode::OwnsGeometry); root-> setFlag (QSGNode::OwnsMaterial); } if (m_needUpdate) { QSGFlatColorMaterial* material = new QSGFlatColorMaterial; material-> setColor (m_color); root-> setMaterial (material); m_needUpdate = false ; } return root; } QColor QQuickCustomItem::color () const { return m_color; } void QQuickCustomItem::setColor ( const QColor& color) { if (m_color != color) { m_color = color; m_needUpdate = true ; update (); colorChanged (); } } Copy code

main.qml file

import QtQuick 2.3 import QtQuick.Window 2.2 import main.qml 1.0 Window { width : 800 height : 800 visible : true Rectangle { width : 200 height : 200 anchors.centerIn: parent color : "lightgrey" Triangle { id : rect width : 200 height : 200 transformOrigin : Item.Top color : "green" onColorChanged : console .log( "color was changed" ); PropertyAnimation on rotation { from : 0 to : 360 duration : 5000 loops : Animation.Infinite } } } Timer { interval : 1000 repeat : true running : true onTriggered : rect.color = Qt.rgba( Math .random(), Math .random(), Math .random(), 1 ); } } Copy code

main.cpp file

# include <QGuiApplication> # include <QQmlApplicationEngine> # include "QQuickCustomItem.h" int main ( int argc, char *argv[]) { # if defined(Q_OS_WIN) QCoreApplication:: setAttribute (Qt::AA_EnableHighDpiScaling); # endif QGuiApplication app (argc, argv) ; //Old 9.School-Technology: Use custom components to display triangle animation qmlRegisterType<QQuickCustomItem>( "main.qml" , 1 , 0 , "Triangle" ); QQmlApplicationEngine engine; engine. load ( QUrl ( QStringLiteral ( "qrc:/main.qml" ))); if (engine. rootObjects (). isEmpty ()) return -1 ; return app. exec (); } Copy code

running result

Integration with C++

We can create QtQuick views directly from C++, and can also expose C++-defined functions to QML.

main.cpp file

#include <QGuiApplication> #include <QQmlApplicationEngine> #include "QQuickCustomItem.h" #include <QQuickView> #include <QQmlContext> int main ( int argc, char *argv[]) { # if defined (Q_OS_WIN) QCoreApplication:: setAttribute (Qt::AA_EnableHighDpiScaling) ; # endif QGuiApplication app (argc, argv) ; QQuickView view; view.setSource(QStringLiteral( "main.qml" )); //Retrieving the QML context. This context allows us to expose data to the QML components QQmlContext* rootContext = view.rootContext(); //Creating 2 new properties: the width and height of the view rootContext->setContextProperty( "WINDOW_WIDTH" , 640 ); rootContext->setContextProperty( "WINDOW_HEIGHT" , 360 ); //Let's display the view view.show(); return app.exec(); } Copy code

main.qml file

import QtQuick 2.3 Rectangle { //We can now access the properties we defined from C++ from the whole QML file width : WINDOW_WIDTH height : WINDOW_HEIGHT Text { text : qsTr( "Hello World" ) anchors.centerIn: parent } } Copy code

running result

Qt5 version update

If it is the Qt5.x version, then we can replace the QQuickView class with the QQmlApplicationEngine class to load and render QML scripts. Modify the code as follows:

Modify main.cpp

# include <QGuiApplication> # include <QQmlApplicationEngine> # include "QQuickCustomItem.h" # include <QQuickView> # include <QQmlContext> int main ( int argc, char *argv[]) { # if defined(Q_OS_WIN) QCoreApplication:: setAttribute (Qt::AA_EnableHighDpiScaling); # endif QGuiApplication app (argc, argv) ; QQmlApplicationEngine engine; QQmlContext* rootContext = engine. rootContext (); rootContext-> setContextProperty ( "WINDOW_WIDTH" , 640 ); rootContext-> setContextProperty ( "WINDOW_HEIGHT" , 360 ); engine. load ( QUrl ( QStringLiteral ( "qrc:/main.qml" ))); return app. exec (); } Copy code

Modify main.qml

import QtQuick 2.3 import QtQuick.Window 2.2 Window { //Must be this type to be loaded by QQmlApplicationEngine. visible : true width : WINDOW_WIDTH //Accessing global context declared in C++ height : WINDOW_HEIGHT //Accessing global context declared in C++ title : qsTr( "Hello World" ) Component.onCompleted: { //We can access global context from within JavaScript too. console .debug( "Width: " + WINDOW_WIDTH) console .debug( "Height:" + WINDOW_HEIGHT) } MouseArea { anchors.fill: parent onClicked : { Qt.quit(); } } Text { text : qsTr( "Hello World! and click here to quit the programm." ) anchors.centerIn: parent } } Copy code

running result

At last

Remember to follow+Like+Favorite+Comment+Repost

Author: Old 9.Academy Technology

The copyright belongs to the author. For commercial reprints, please contact the author for authorization. For non-commercial reprints, please indicate the source.