[исходный код проекта можно скачать здесь]
Создадим новый проект в Clickable, в терминале вводим команду:
clickable create
Выбираем тип проекта Python и заполняем:
Title [App Title]: Calculator
App Name [appname]: example-сalculator
В папке с проектом находи Main.qml удаляем все лишнее - Python объект, Label в Page.
Первое, что нам понадобится, это поле ввода для нашего калькулятора.
TextField {
id: textField
text: ""
property bool hasError: false
font.italic: hasError
anchors {
topMargin: units.gu(1);
top: header.bottom
left: parent.left
leftMargin: units.gu(1);
right: parent.right
rightMargin: units.gu(1);
}
height: units.gu(8)
font.pixelSize: units.gu(4)
}
Что бы наше текстовое поле не перекрывало заголовок в anchors мы устанавливаем выравнивание top: header.bottom. Таким образом, наше поле будет сразу перед заголовком.
Так же необходимо понимать, что на разных устройствах, разное разрешение дисплея, поэтому необходимо всегда указывать относительный размер, в этом нам поможет свойство units.gu(1), которое и будет указывать относительный размер.
Результат программы может быть с ошибками(например деление на ноль), для этого мы объявим свойство property bool hasError, которое в случае ошибки сделает шрифт наклонным(font.italic: hasError).
Теперь создадим кнопки - в папке qml создадим файл CalculatorButton.qml:
import QtQuick 2.7
import Ubuntu.Components 1.3
Rectangle {
signal clicked
color: "#AEA79F"
radius: units.gu(1)
border.width: units.gu(0.25)
border.color: "white"
property alias text: label.text
property alias color_text: label.color
Label {
id: label
font.pixelSize: units.gu(4)
anchors.centerIn: parent
color: "#111"
}
MouseArea {
id: mouseArea
anchors.fill: parent
onClicked: parent.clicked()
}
}
Наша кнопка, это обычный прямоугольник и она ни как не может взаимодействовать(исполнять функцию кнопки). Что бы это исправить объявим сигнал clicked(signal clicked).
Для создания этого события создадим MouseArea. Установим обтекание по родителю(anchors.fill: parent) и передачу события нажатие родителю(onClicked: parent.clicked())
Так же мы создали нашему объекту 2 свойства - text(для изменения текста) и color_text(для изменения цвета шрифта)
Импортируем это в основной наш проект Main.qml, добавим в заголовке import "./"
Кнопок нашем в калькуляторе много и они однотипны.
/ 1 2 3
* 4 5 6
- 7 8 9
+ , 0 =
Создадим слой сетку размером 4x4.
Для того, что бы создать однотипные кнопки добавим Repeater по модели ("/", 1, 2, 3, "*", 4, 5, 6, "-", 7, 8, 9, "+", ",", 0)
Grid {
anchors {
top: textField.bottom
left: parent.left
right: parent.right
bottom: parent.bottom
}
columns: 4
rows: 4
Repeater {
model: ["/", 1, 2, 3, "*", 4, 5, 6, "-", 7, 8, 9, "+", ",", 0]
delegate: CalculatorButton {
text: modelData.toString ()
height: parent.height / parent.rows
width: parent.width / parent.columns
color: {
if ((index % 4 == 0) || (modelData.toString() == ","))
{
color_text = "white"
return "#E95420"
} else {
return "#AEA79F"
}
}
}
}
На каждой кнопки мы меняем текст, присуждая ей modelData.toString()(элемент репитора). Так же мы можем получать индекс элемента репитора, через свойство index.
Для лучшего отображения, меняем цвет кнопки, по правилу если остаток от деления на 4 равен 0 или содержимое элемента совпадает с ",", то меняем цвет кнопки на #E95420 и цвет текста на белый.
Получаем:
Осталось добавить только кнопку "=". После репитора добавим:
CalculatorButton {
text: "="
color: "#5E2750"
color_text : "white"
height: parent.height / parent.rows
width: parent.width / parent.columns
}
Теперь подключим Python
Python {
id: python
Component.onCompleted: {
addImportPath(Qt.resolvedUrl('../src/'));
importModule_sync("example")
}
onError: {
console.log('python error: ' + traceback);
}
}
Добавим обработку нашего кода. В Repeater добавляем событие onClicked:
Repeater {
...
delegate: CalculatorButton {
...
onClicked: textField.text += modelData.toString()
...
}
}
При нажатие кнопки, мы будем добавлять соответствующий символ в нашу строку. Теперь подключим исполнение математической строки. К кнопке равно добавим событие:
CalculatorButton {
...
onClicked: {
python.call("example.calculate", [ textField.text ], function ( result ) {
var isValid = result[0];
if (isValid) {
textField.hasError =false
textField.text = result[1];
} else {
textField.hasError =true
}
})
}
...
}
Теперь запустим наше приложение:
Как можно заметить, наш калькулятор способен на большее чем 2+2. Что бы вычислять более сложные функции их можно ввести в строку ввода.