Good afternoon,% username%!
A little background:
Some time ago, I did a laboratory friend, whose subject is the Hamming code. The program was an ordinary Qt application with a minimum set of controls. The delivery was successful, some time has passed, and now his friend also needs to pass a laboratory on the same subject. The same program, obviously, can not be passed. Then the question arises - how to make a program with three buttons and two text boxes unlike the previous one? I had the idea to rewrite the interface using Qt Quick, and leave the logic and calculations of the program in C ++, and at the same time tell interested people how I usually do things like that. According to Qt Quick, there is not so much literature, especially in Russian, so I really hope that this article will be useful and interesting.
To clarify, the focus is on how Qt Quick interacts with C ++, to a lesser extent, the basics of Qt and QML, but not the counting of Hamming codes.
')
Creation of the frame
So, the last seconds of installing Qt Sdk in my work, we are starting.
Open QtCreator, create a new project like “Qt GUI application”. Select a directory, name, then in this window of the wizard:

remove the checkbox "Create form". We do not need it, we will write the entire interface with pens.
In the generated mainwindow.h file, include the following header files:
#include #include <QtDeclarative / QDeclarativeContext>
#include <QtDeclarative / QDeclarativeView>
In the constructor of the class MainWindow make the following changes:
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
{
QDeclarativeView* dv = new QDeclarativeView();
dv->setSource(QUrl("qrc:/main.qml"));
QDeclarativeContext* cntx = dv->rootContext();
cntx->setContextProperty("window",this);
dv->setResizeMode(QDeclarativeView::SizeRootObjectToView);
setCentralWidget(dv);
}
I will explain a little bit - we create a widget of the type QDeclarativeView - this is an element capable of displaying QML. Then we set the name of the root QML element - main.qml, which is taken from the resources that we add later. Then we get the context of the widget to add a new property “window” in it. Now from QML it will be possible to access the object called window - this is our form. Why this is needed will become clear a little later. The resizing mode is set below - now the root QML element will resize according to the window, and not vice versa. The setCentralWidget method sets a central widget for QMainWindow. Anyone who has experienced Qt is undoubtedly familiar with it.
Our project needs a QML file, as mentioned above. Add it:

Now add the resource file in a similar way:

It opens automatically, click “Add” -> “Add prefix” below, “/ new / prefix1” appears. We erase and leave only “/” for simplicity. Now add the main.qml file (“Add” -> “Add file”). Another little thing - you need to make one change to the * .pro file
QT + = core declarative
In this simple way, we expose the project to a dependency on the QtDeclarative4 library.
Now you can safely run the project and see ... White square 100 to 62 :) But appearance is deceptive - in fact it is much more than a white square, this application, whose interface is written in QML, and the logic in C ++.
Something like this begins the creation of any application that will be a hybrid of Qt Quick and C ++. The main point is getting the root context of the QDeclarativeView widget, adding a new property to access the C ++ object. This property will become a kind of bridge between QML and C ++.
Creation of interface and logic
So, the creation of the base is passed, now the logic of the work.
In the mainwindow.h file we add to the class description
public slots:
QString slotEncode(QString sIn);
QString slotDecode(QString sIn);
bool slotCheck(int val);
By name it is clear that the first two slots will be engaged in coding and decoding. Both will accept the input string that the user enters in QML, and return, respectively, the encoded or decoded version. Why slots instead of ordinary functions? Because it is slots, as well as functions, declared using the Q_INVOKABLE macro (see the documentation for details) can be called from QML by referring to an object made visible using setContextProperty (). Simply put, it will be possible to write window.slotEncode () in QML :) Also, all the properties declared using the Q_PROPERTY macro are available from the QML code - they can be accessed directly by name.
I will take the implementation of these slots from the old project, and will not give them here in full, you can download the archive from the link below. There is also a small reservation - in the process of encoding and decoding a table is built, which I didn’t want to rewrite at all, so it will remain in its original form and will simply be shown in a separate window. A slotCheck (int v) slot was also added for service purposes, used only in the process of counting the code, and of course, you need to add it, but you shouldn’t think at all what it is for - because it doesn’t belong to the lesson!
Now it remains only to make the program interface :)
Perhaps, I will give out that version of the interface, which is done in 15 minutes, by an ordinary programmer without a creative view of the world (although usually my girl artist helps me to do such things):
import QtQuick 1.0
Rectangle {
width: 365
height: 200
gradient: Gradient {
GradientStop {
position: 0
color: "#696363"
}
GradientStop {
position: 1
color: "#000000"
}
}
Text {
id: text1
x: 37
y: 27
color: "#fbfbfb"
text: " "
style: Text.Raised
font.pixelSize: 12
}
Text {
id: text2
x: 198
y: 27
color: "#ffffff"
text: " "
style: Text.Raised
font.pixelSize: 12
}
// .
Rectangle {
color: "#4de013"
radius: 6
border.width: 5
border.color: "#f5f9f4"
x: 36
y: 66
width: 133
height: 20
TextInput {
id: text_input1
width: parent.width - 20
height: parent.height - 5
anchors.horizontalCenter: parent.horizontalCenter
anchors.verticalCenter: parent.verticalCenter
text: ""
font.pixelSize: 12
}
}
// .
Rectangle {
color: "#48c819"
radius: 6
border.width: 5
border.color: "#f5f9f4"
width: 133
height: 20
x: 201
y: 66
TextInput {
id: text_input2
width: parent.width - 20
height: parent.height - 5
anchors.horizontalCenter: parent.horizontalCenter
anchors.verticalCenter: parent.verticalCenter
text: ""
font.pixelSize: 12
}
}
// .
Rectangle {
id: bEncode
property alias text: label.text
width: 135
height: 60
radius: 20
border.width: 2
border.color: "#090606"
gradient: Gradient {
GradientStop {
id: gradientstop1
position: 0.01
color: "#ffffff"
}
GradientStop {
id: gradientstop2
position: 0.28
color: "#867d7d"
}
GradientStop {
id: gradientstop3
position: 1
color: "#000000"
}
}
signal clicked()
x: 36
y: 110
Text {
id: label
color: "#ffffff"
text: ""
font.strikeout: false
font.pointSize: 10
horizontalAlignment: Text.AlignHCenter
anchors.centerIn: parent
}
MouseArea {
id: mouseArea
anchors.fill: parent
hoverEnabled: true
onClicked: {
text_input2.text = window.slotEncode(text_input1.text)
}
onEntered: {
bEncode.state = "green"
}
onExited: {
bEncode.state = "gray"
}
}
states: [
State {
name: "gray"
},
State {
name: "green"
PropertyChanges {
target: gradientstop1
color: "#ffffff"
}
PropertyChanges {
target: gradientstop2
color: "#34c22a"
}
PropertyChanges {
target: gradientstop3
color: "#000000"
}
}
]
}
// .
Rectangle {
id: bDecode
property alias text: label.text
width: 136
height: 60
radius: 20
border.width: 2
border.color: "#090606"
gradient: Gradient {
GradientStop {
id: gradientstop21
position: 0.01
color: "#ffffff"
}
GradientStop {
id: gradientstop22
position: 0.28
color: "#867d7d"
}
GradientStop {
id: gradientstop23
position: 1
color: "#000000"
}
}
signal clicked()
x: 200
y: 110
Text {
id: label2
text: ""
color: "#ffffff"
font.strikeout: false
font.pointSize: 10
horizontalAlignment: Text.AlignHCenter
anchors.centerIn: parent
}
MouseArea {
id: mouseArea2
anchors.fill: parent
hoverEnabled: true
onClicked: {
text_input1.text = window.slotDecode(text_input2.text)
}
onEntered: {
bDecode.state = "green"
}
onExited: {
bDecode.state = "gray"
}
}
states: [
State {
name: "gray"
},
State {
name: "green"
PropertyChanges {
target: gradientstop21
color: "#ffffff"
}
PropertyChanges {
target: gradientstop22
color: "#34c22a"
}
PropertyChanges {
target: gradientstop23
color: "#000000"
}
}
]
}
}
I'm not at all sure if the syntax will be highlighted correctly - let's hope that the similarity with JavaScript will play its positive role!
Link to the source -
Tyk!Result of work:

Small total
The result of our work was a hybrid application. In the future, the creation of such applications allows you to combine non-standard QtQuick interface with high-performance C ++ code. I hope the article will be useful to those interested in these technologies, because the questions "Give Qt Quick literature" are becoming more common. Thanks for attention!