Файл: Kivy Создание мобильных приложений на Python.docx

ВУЗ: Не указан

Категория: Не указан

Дисциплина: Не указана

Добавлен: 06.12.2023

Просмотров: 41

Скачиваний: 1

ВНИМАНИЕ! Если данный файл нарушает Ваши авторские права, то обязательно сообщите нам.

В данном коде вызывается button.bind(), а событие on_press ссылается на MainApp.on_press_button().

Этот метод неявно принимает экземпляр виджета, который является самим объектом кнопки. Сообщение будет выводиться на stdout всякий раз при нажатии пользователем на кнопку.

Использование языка дизайна KV

Kivy предоставляет язык дизайна KV, что можно использовать в приложениях Kivy. Язык KV позволяет отделить дизайн интерфейса от логики приложения. Он придерживается принципа разделения ответственности и является частью архитектурного паттерна Модель-Представление-Контроллер (Model-View-Controller).  Предыдущий пример можно обновить, используя язык KV:

Python

1

2

3

4

5

6

7

8

9

10

11

12

13

from kivy.app import App

from kivy.uix.button import Button

 

class ButtonApp(App):

    def build(self):

        return Button()

 

    def on_press_button(self):

        print('Вы нажали на кнопку!')

 

if __name__ == '__main__':

    app = ButtonApp()

    app.run()

С первого взгляда данный код может показаться несколько странным, так как кнопка Button создается без указания атрибутов или привязывания к ним событий. Здесь Kivy автоматически ищет файл с таким же названием, что и у класса, только строчными буквами и без части App в названии класса.

В данном случае названием класса является ButtonApp, поэтому Kivy будет искать файл button.kv. Если такой файл существует, и он также форматирован должным образом, тогда Kivy использует его при загрузке UI. Попробуйте создать такой файл и добавить следующий код:

Python

1

2

3

4

5


Действия каждой строки:

  • Строка 1 соответствует вызову Button в коде Python. Kivy должен осмотреть инициализированный объект для определения кнопки;

  • Строка 2 устанавливает text кнопки;

  • Строка 3 устанавливает ширину и высоту при помощи size_hint;

  • Строка 4 устанавливает позицию кнопки через pos_hint;

  • Строка 5 устанавливает обработчик событий on_press. Для указания Kivy места обработчика событий используется app.on_press_button(). Здесь Kivy будет искать метод .on_press_button() в классе Application.

Вы можете установить все ваши виджеты и лейауты внутри одного или нескольких файлов языка KV. Язык KV также поддерживает 
импорт модулей Python в KV, создавая динамичные классы, и это далеко не предел. Ознакомиться с полным перечнем его возможностей можно в гиде Kivy по языку KV.

Теперь мы можем приступить к созданию настоящего рабочего приложения.

Создание приложения Kivy Python

Создание чего-то полезное несомненно является отличным способом выучить новый навык. Учитывая данное утверждение, давайте используем Kivy при создании калькулятора, который будет поддерживать следующие операции:

  • Сложение;

  • Вычитание;

  • Умножение;

  • Деление.

В данном приложении будет использован набор кнопок в своего рода лейауте. В верхней части также будет специальный блок для вывода операций и их результатов. В итоге калькулятор будет выглядеть следующим образом:



Теперь, когда у нас есть в наличии целевой UI, может составить код:

Python

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

from kivy.app import App

from kivy.uix.boxlayout import BoxLayout

from kivy.uix.button import Button

from kivy.uix.textinput import TextInput

 

class MainApp(App):

    def build(self):

        self.operators = ["/", "*", "+", "-"]

        self.last_was_operator = None

        self.last_button = None

        main_layout = BoxLayout(orientation="vertical")

        self.solution = TextInput(

            multiline=False, readonly=True, halign="right", font_size=55

        )

        main_layout.add_widget(self.solution)

        buttons = [

            ["7", "8", "9", "/"],

            ["4", "5", "6", "*"],

            ["1", "2", "3", "-"],

            [".", "0", "C", "+"],

        ]

        for row in buttons:

            h_layout = BoxLayout()

            for label in row:

                button = Button(

                    text=label,

                    pos_hint={"center_x": 0.5, "center_y": 0.5},

                )

                button.bind(on_press=self.on_button_press)

                h_layout.add_widget(button)

            main_layout.add_widget(h_layout)

 

        equals_button = Button(

            text="=", pos_hint={"center_x": 0.5, "center_y": 0.5}

        )

        equals_button.bind(on_press=self.on_solution)

        main_layout.add_widget(equals_button)

 

        return main_layout

Калькулятор работает следующим образом:

  • В строках с 8 по 10 создается список operators и несколько полезных значений, last_was_operator и last_button, которые будут использованы чуть позже.

  • В строках с 11 по 15 создается лейаут верхнего уровня main_layout, к нему также добавляется виджет только для чтения TextInput.

  • В строках с 16 по 21 создается вложенный список из списков, где есть большая часть кнопок для калькулятора.

  • В строке 22 начинается цикл for для кнопок. Для каждого вложенного списка делается следующее:


  1. В строке 23 создается BoxLayout с горизонтальной ориентацией.

  2. В строке 24 начинается еще один цикл for для элементов вложенного списка.

  3. В строках с 25 по 39 создаются кнопки для ряда и связываются обработчиком событий, после чего кнопки добавляются к горизонтальному BoxLayout из строки 23.

  4. В строке 31 этот лейаут добавляется к main_layout.

  • В строках с 33 по 37 создается кнопка равно (=) и привязывается к обработчику событий, после чего она добавляется к main_layout.

    Далее создается обработчик событий .on_button_press(). Код будет выглядеть следующим образом:

    Python

    1

    2

    3

    4

    5

    6

    7

    8

    9

    10

    11

    12

    13

    14

    15

    16

    17

    18

    19

    20

    def on_button_press(self, instance):

        current = self.solution.text

        button_text = instance.text

     

        if button_text == "C":

            # Очистка виджета с решением

            self.solution.text = ""

        else:

            if current and (

                self.last_was_operator and button_text in self.operators):

                # Не добавляйте два оператора подряд, рядом друг с другом

                return

            elif current == "" and button_text in self.operators:

                # Первый символ не может быть оператором

                return

            else:

                new_text = current + button_text

                self.solution.text = new_text

        self.last_button = button_text

        self.last_was_operator = self.last_button in self.operators

    Почти все виджеты приложения вызывают .on_button_press(). Это работает следующим образом:

    • Строка 41 принимает аргумент instance, в результате чего можно узнать, какой виджет вызвал функцию.

    • Строки между 42 и 43 извлекают и хранят значения solution и text кнопки.

    • Строки c 45 по 47 проверяют, на какую кнопку нажали. Если пользователь нажимает с, тогда очищается solution. В противном случае используется утверждение else.

    • Строка 49 проверяет, было ли у решения предыдущее значение.

    • Строки с 50 по 52 проверяют, была ли последняя нажатая кнопка оператором. Если да, тогда solution обновляться не будет. Это необходимо для предотвращения создания двух операций в одном ряду. К примеру, 1 * / будет недействительным утверждением.

    • Строки с 53 по 55 проверяют, является ли первый символ оператором. Если да, тогда solution обновляться не будет, так как первое значение не может быть значением оператора.

    • Строки с 56 по 58 переходят к условию else. Если никакое из предыдущих значений не найдено, тогда обновляется solution.

    • Строка 59 устанавливает last_button к метке последней нажатой кнопки.

    • Строка 60 устанавливает last_was_operator к значению True или False в зависимости от того, был символ оператором или нет.


    Последней частью кода будет .on_solution():

    Python

    1

    2

    3

    4

    5

    def on_solution(self, instance):

        text = self.solution.text

        if text:

            solution = str(eval(self.solution.text))

            self.solution.text = solution

    Здесь берется текущий текст из solution и используется встроенный в Python eval() для исполнения. Если пользователь создал формулу вроде 1+2, тогда eval() запустит код и вернет результат. В конце результат устанавливается как новое значение виджета solution.

    На заметку: порой eval() бывает опасным, так как он может запустить произвольный код. Многие разработчики избегают его использование именно по этой причине. Тем не менее, ввиду задействования только целых чисел, операторов и точки в качестве вводных данных для eval(), в данном контексте его можно использовать безопасно.

    При запуске данного кода на рабочем столе компьютера приложение будет выглядеть следующим образом:



    Полный текст кода примера калькулятора представлен ниже:

    Python

    1

    2

    3

    4

    5

    6

    7

    8

    9

    10

    11

    12

    13

    14

    15

    16

    17

    18

    19

    20

    21

    22

    23

    24

    25

    26

    27

    28

    29

    30

    31

    32

    33

    34

    35

    36

    37

    38

    39

    40

    41

    42

    43

    44

    45

    46

    47

    48

    49

    50

    51

    52

    53

    54

    55

    56

    57

    58

    59

    60

    61

    62

    63

    64

    65

    66

    67

    68

    69

    70

    71

    from kivy.app import App

    from kivy.uix.boxlayout import BoxLayout

    from kivy.uix.button import Button

    from kivy.uix.textinput import TextInput

     

    class MainApp(App):

        def build(self):

            self.operators = ["/", "*", "+", "-"]

            self.last_was_operator = None

            self.last_button = None

            main_layout = BoxLayout(orientation="vertical")

            self.solution = TextInput(

                multiline=False, readonly=True, halign="right", font_size=55

            )

            main_layout.add_widget(self.solution)

            buttons = [

                ["7", "8", "9", "/"],

                ["4", "5", "6", "*"],

                ["1", "2", "3", "-"],

                [".", "0", "C", "+"],

            ]

            for row in buttons:

                h_layout = BoxLayout()

                for label in row:

                    button = Button(

                        text=label,

                        pos_hint={"center_x": 0.5, "center_y": 0.5},

                    )

                    button.bind(on_press=self.on_button_press)

                    h_layout.add_widget(button)

                main_layout.add_widget(h_layout)

     

            equals_button = Button(

                text="=", pos_hint={"center_x": 0.5, "center_y": 0.5}

            )

            equals_button.bind(on_press=self.on_solution)

            main_layout.add_widget(equals_button)

     

            return main_layout

     

        def on_button_press(self, instance):

            current = self.solution.text

            button_text = instance.text

     

            if button_text == "C":

                # Очистка виджета с решением

                self.solution.text = ""

            else:

                if current and (

                    self.last_was_operator and button_text in self.operators):

                    # Не добавляйте два оператора подряд, рядом друг с другом

                    return

                elif current == "" and button_text in self.operators:

                    # Первый символ не может быть оператором

                    return

                else:

                    new_text = current + button_text

                    self.solution.text = new_text

            self.last_button = button_text

            self.last_was_operator = self.last_button in self.operators

     

        def on_solution(self, instance):

            text = self.solution.text

            if text:

                solution = str(eval(self.solution.text))

                self.solution.text = solution

     

     

    if __name__ == "__main__":

        app = MainApp()

        app.run()


    Пришло время разместить приложение в Google Play или в AppStore!

    Создаем apk приложения для Android на Python

    По завершении составления кода вы можете поделиться своим приложением с другими. Хорошим способом сделать это может стать превращение вашего кода в приложения для смартфона на Android. Для этого вначале нужно установить пакет buildozer через pip:

    Shell

    1

    $ pip install buildozer

    Затем создается новая папка, после чего нужно перейти в нее через терминал. Затем выполняется следующая команда:

    Shell

    1

    $ buildozer init

    После этого создается файл buildozer.spec, который будет использован для конфигурации сборки. К примеру, первые две строчки файла спецификации можно редактировать следующим образом:

    Shell

    1

    2

    3

    4

    5

    6

    7

    8

    9

    10

    [app]

     

    # (str) Название вашего приложения

    title = KvCalc

     

    # (str) Название упаковки

    package.name = kvcalc

     

    # (str) Домен упаковки (нужен для упаковки android/ios)

    package.domain = org.kvcalc

    Не бойтесь посмотреть оставшуюся часть файла для выяснения того, что еще можно поменять.

    На данный момент приложение почти готово к сборке, однако для начала нужно установить зависимости для buildozer.  После их установки скопируйте ваше приложение калькулятора в новую папку и переименуйте его в main.py. Этого требует buildozer. Если файл будет назван неверно, тогда процесс сборки завершится неудачей.

    Теперь можно запустить следующую команду:

    Shell

    1

    $ buildozer -v android debug

    Этап сборки займет время! На моем компьютере на это ушло около 15-20 минут. Здесь все зависит от вашего железа, так что времени может потребоваться еще больше. Расслабьтесь, налейте чашечку кофе или прогуляйтесь. Buildozer скачает те элементы Android SDK, которые нужны для процесса сборки. Если все идет по плану, тогда в папке bin появится файл под названием, напоминающим что-то вроде kvcalc-0.1-debug.apk.

    Далее требуется связать телефон Android с компьютером и перенести туда файл apk. Затем откройте менеджер файлов телефона и кликните на файл apk. Android должен спросить, хотите ли вы установить приложение. Есть вероятность появления предупреждения, ведь приложение было скачано не из Google Play