404

Пишем калькулятор на Python для Ubuntu Touch

[исходный код проекта можно скачать здесь]

Создадим новый проект в 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 и цвет текста на белый.
Получаем:

ubuntu_toch_python5.png

Осталось добавить только кнопку "=". После репитора добавим:

CalculatorButton {
    text: "="
    color: "#5E2750"
    color_text : "white"
    height: parent.height / parent.rows
    width: parent.width / parent.columns
}

ubuntu_toch_python6.png

Теперь подключим 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  
            }
        })
        }
    ...
}

Теперь запустим наше приложение:

ubuntu_toch_python7.png

Как можно заметить, наш калькулятор способен на большее чем 2+2. Что бы вычислять более сложные функции их можно ввести в строку ввода.