Kivy Python

Kivy Python

Kivy это фреймворк  на Python с открытым исходным кодом для разработки кроссплатформенных приложений.

Нашел этот фреймворк, когда понадобилось написать мобильное приложения для получение данных по API с сайта на Django, вроде показался не очень сложным, а главное позволил создать приложение для Android на Python.

Это не учебник и не подробная статья по Kivy, а просто пример создания приложения уровня HelloWorld.

Для начала установим Kivy, согласно официальной документации через pip это делается командой:

pip install kivy[base]

Первая программа на фреймворке Kivy

После установки, проверим работоспособность kivy создав простое первое приложение, которое выведет нам Привет мир!

Создадим файл hello.py со следующим содержимым:

from kivy.app import App
from kivy.uix.label import Label


class MainApp(App):
    def build(self):
        label = Label(text='Привет мир!')
        return label


if __name__ == '__main__':
    app = MainApp()
    app.run()

Запускаем и видим наше приложение:

Первое приложение на фреймворке kivy

Каждому приложению Kivy требуется создать подкласс App и переопределить метод build(), что мы и сделали. Сюда мы поместили код, который создает виджет Label с переданным значением text.

В Kivy все элементы располагаются на layout и чтобы вывести несколько элементов (например слова «привет» и «мир» мы хотим разместить на разных виджетах Label), нам нужно расположить их на нем.

Всего существует 8 видов лайаутов, о них можно почитать в официальной документации:  https://kivy.org/doc/stable/gettingstarted/layouts.html

Для нашего примера будем использовать BoxLayout, в нем все элементы располагаются друг за другом при горизонтальной ориентации или друг под другом при вертикальной.

Изменим метод build чтобы он возвращал нам не один элемент интерфейса, а слой с несколькими элементами:

    def build(self):
        layout = BoxLayout()

        label1 = Label(text='Привет')
        label2 = Label(text='мир!')


        layout.add_widget(label1)
        layout.add_widget(label2)

        return layout

Не забудем импортировать BoxLayout

from kivy.uix.boxlayout import BoxLayout

Теперь запустим и увидим нужный результат:

Программа на kivy с двумя виджетами Label на BoxLayout

Все работает, но не видно где заканчивается один Label и начинается второй. Например, я хочу поменять фон и работать с позиционированием элементов, для этого в киви существует язык разметки.

Сделаем отдельный файл с этой разметкой, он должен иметь расширение kv, по умолчанию метод run() будет искать с файл с именем нашего класса без App, т.е. в нашем случае main.kv

Перепишем пример выше, сначала код файла main.kv:

<MainWidget>:

    Label:
        text: 'Привет'

    Label:
        text: 'Мир'

Теперь изменим код hello.py на:

from kivy.app import App
from kivy.uix.boxlayout import BoxLayout


class MainWidget(BoxLayout):
    pass


class MainApp(App):

    def build(self):
        return MainWidget()


if __name__ == '__main__':
    app = MainApp()
    app.run()

Запускаем скрипт и мы должны увидеть все тоже самое, если так, то ничего не сломалось и можно продолжить.

Начнем доработку внешнего вида, для этого поменяем файл main.kv. Во первых сделаем разные цвета для наших Label и отделим их друг от друга:

<MainWidget>:
    orientation: 'vertical'
    padding: 20
    spacing: 20

    Label:
        markup: True
        text: '[color=000000]Привет[/color]'
        canvas.before:
            Color:
                rgba: 1, 1, 1, 1
            Rectangle:
                pos: self.pos
                size: self.size
    Label:
        text: 'Мир'
        canvas.before:
            Color:
                rgba: 1, .5, 0, 1
            Rectangle:
                pos: self.pos
                size: self.size

Проверяем:

Работа с внешнем видом в фреймворке kivy

Усложняем программу

Теперь сделаем программу чуть сложнее чем Helloworld, сделаем чтобы мы вводили в нее свое имя и она с нами здоровалась.

Она должна выглядеть вот так:

Конечная программа на фреймворке Kivy Python

Сверху картинка, потом поле ввода, потом надпись, потом кнопка.

Файл шаблона (main.kv) у меня получился таким:

<MainWidget>:
    orientation: 'vertical'
    padding: 20
    spacing: 20

    Image:
        source: 'hello.png'

    TextInput:
        multiline: False
        size_hint: (.5, None)
        pos_hint:{"center_x":0.5, "top":1}
        height: 50
        font_size: 30

    Label:
        font_size: 30
        text: 'Напишите как вас зовут'

    Button:
        font_size: 30
        text: 'Поздороваться'
        size_hint: (.5, None)
        pos_hint:{"center_x":0.5, "top":1}

hello.png — это файл с картинкой с надписью hello, в моем случае он лежит в корне проекта

Теперь осталось сделать чтобы программа выполняла свою функцию и здоровалась с нами по нажатию кнопки «Поздороваться».

Сначала добавим в класс MainWidget добавим метод say_hello():

class MainWidget(BoxLayout):

    def say_hello(self):
        print('тест кнопки')

Он будет вызываться по нажатию кнопки. Для того чтобы кнопка реагировала на нажатие, добавим ей атрибут on_press, который будет вызывать метод say_hello():

Button:
        font_size: 30
        text: 'Поздороваться'
        size_hint: (.5, None)
        pos_hint:{"center_x":0.5, "top":1}

        on_press: root.say_hello()

Если сейчас запустить программу и нажать на кнопку «Поздороваться», то в консоли мы получим сообщение «тест кнопки».

Если так, то пока все работает правильно smiley

Дальше нужно сделать, чтобы в Label менялся текст на тот, который введен в виджете TextInput.

Для этого нам нужно получить доступ к свойству text этих виджетов.

Для этого импортируем класс ObjectProperty и создадим 2 экземпляра этого класса:

from kivy.properties import ObjectProperty


class MainWidget(BoxLayout):
    hello_label = ObjectProperty()
    name_input = ObjectProperty()

    def say_hello(self):
...

Теперь откроем файл main.kv и добавим индефикаторы для виджетов Label и TextInput, чтобы на них можно было ссылаться из других частей KV файла.

TextInput:
        id: name

Label:
        id: hello

Теперь установим эти индефикаторы в значения свойств hello_label и name_input, которые мы определили в методе say_hello():

<MainWidget>:
    orientation: 'vertical'
    padding: 20
    spacing: 20

    name_input: name
    hello_label: hello
...

Теперь мы можем получить доступ к свойству text этих виджетов, изменим методе say_hello():

def say_hello(self):
        self.hello_label.text = 'Привет ' + self.name_input.text

Собственно все, можно запустить программу и проверить, все должно работать.

Конечная программа на фреймворке Kivy Python

Весь код файлов есть в репозитории на гитхабе https://github.com/alexandrtretyakov/kivy

Хостинг для ваших проектов