404

Взаимодействуем с QML интерфейсом через Python на Ubuntu Touch

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

Создадим новый проект в Clickable, в терминале вводим команду:

clickable create

Выбираем тип проекта Python и заполняем:
Title [App Title]: Progress Bar
App Name [appname]: exemple-progress-bar

В папке с проектом находи Main.qml удаляем все лишнее - Python объект, Label в Page.

Теперь создадим интерфейс:

Text {
    id: label1
    text: qsTr("Download...")
    color: "#5E2750"
    anchors{
        verticalCenterOffset: -units.gu(4)
        verticalCenter: parent.verticalCenter
        left: parent.left
        leftMargin: units.gu(1)
        right: parent.right
    }
    font.pixelSize: units.gu(2)
    }

Rectangle {
    height: units.gu(5)
    color: "white"
    anchors
    {
    verticalCenter: parent.verticalCenter
    right: parent.right
    left: parent.left
    }
    Rectangle {
        color: "#AEA79F"
        anchors.fill: parent
        border.width: units.gu(1)
        radius: units.gu(1.5)
        border.color: "white"
    }    
    Rectangle {
        id: progressbar1
        color: "#E95420"
        property real value: 0
        anchors{
            rightMargin: parent.width/100*(100-value)
            fill: parent
        }
        border.width: units.gu(1)
        radius: units.gu(1.5)
        border.color: "white"
    }
}

Таким образом мы создали Label, для отображения состояния процесса и свой прогресс бар.
Наш прогресс бар это два прямоугольника- полоса состояния и его подложка. Для того, что бы с ним была возможность взаимодействовать назначаем id: progressbar1. Так же добавляем переменную для взаимодействия value. В зависимости от значения этой переменной будет меняться правый отступ от края, по формуле - parent.width/100*(100-value).

Теперь добавим объект Python:

Python {
    id: python1

    Component.onCompleted: {
    addImportPath(Qt.resolvedUrl('../src/'));
    setHandler('progress', function(ratio) {
        progressbar1.value = ratio;
    });
    setHandler('finished', function() {
        label1.text = qsTr("Download complete");
        progressbar1.color = "#5E2750";
    });

    importModule('example', function () {
       startDownload();
    });
    }
    function startDownload() {
        progressbar1.value = 0.0;
        call('example.downloader.download', function() {});
    }

    onError: {
        console.log('python error: ' + traceback);
    }
}

Мы создали 2 события для взаимодействия - progress и finished. Когда мы передаем переменную в progress, у нас будет меняться значение progressbar1.value. А когда мы закончим, через вызов finished, мы выведем сообщение "Download complete" и изменим цвет прогресс бара на фиолетовый.

Что бы начать загрузку мы создали функцию startDownload(). Ее можно вызвать в любом месте кода, через python1.startDownload()(Например при нажатии кнопки). В этом коде эта функция вызывается при инициализации скрипта example.

Теперь переходим в папку src и редактируем example.py:

import pyotherside
import time
import threading

def slow_function():
    for i in range(100):
        pyotherside.send('progress', i)
        time.sleep(0.2)
    pyotherside.send('finished')

class Downloader:
    def __init__(self):
        self.bgthread = threading.Thread()

    def download(self):
        if self.bgthread.is_alive():
            return
        self.bgthread = threading.Thread(target=slow_function)
        self.bgthread.start()

downloader = Downloader()

В этом примере создается новый класс Downloader. При инициализации он создаст новый объект для потока, который и будет взаимодействовать с прогресс баром. Этот процесс можно запустить вручную или повторно, через функцию download.

Для того, что бы с прогресс баром взаимодействовал всегда один процесс, пишем проверку if self.bgthread.is_alive(). В случае если процесс уже запущен, она не создаст новый поток.

Теперь мы можем создать этот объект downloader = Downloader()

В потоке slow_function() мы взаимодействуем с QML через функцию pyotherside.send(). Сперва отправляем значения в progress(0-100), а затем вызываем событие finished.

Осталось только запустить код.

ubuntu_toch_python8.png