25.05.2016       Выпуск 127 (23.05.2016 - 29.05.2016)       Статьи

Расширяем фреймворк Kivy пакетом XPopup Kivy

Не так давно передо мной встала задача в сжатые сра сроки написать работающий прототип GUI-приложения, которое без лишней строки кода хорошо дружило бы как с Windows, так и с OS X. Выбор пал на змеиный фреймворк Kivy, который с легкостью решал вышесказанное. А также, в базовой комплектации имел весь необходимый инструментарий для реализации приложения.

Ну… почти весь. Под катом расскажу что не так и как это побороть.

Читать>>




Экспериментальная функция:

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

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

Эти забавные зверушки

Не так давно передо мной встала задача в сжатые

сра

сроки написать работающий прототип GUI-приложения, которое без лишней строки кода хорошо дружило бы как с Windows, так и с OS X. Выбор пал на змеиный фреймворк

Kivy

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

Ну… почти весь. Под катом расскажу что не так и как это побороть.

Ёж Киви — птица гордая

Фреймворк имеет полезный класс

kivy.uix.popup.Popup

для реализации всплывающих окон. Не буду вдаваться в подробности того, что он умеет — статья не об этом. Кому любопытно — по ссылке можно почитать документацию этого класса и его предка —

kivy.uix.modalview.ModalView

.

Но есть нюансы. Допустим, перед вами стоит банальная задача — вывести текстовое сообщение во всплывающем окне.

Popup

позволяет это сделать довольно просто, в одну строку:

Popup(title='Уведомление', content=Label(text='Получено новое сообщение')).open()

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

layout = BoxLayout(orientation="vertical")
layout.add_widget(Label(text='Получено новое сообщение'))
button = Button(text='Закрыть')
layout.add_widget(button)
popup = Popup(title='Уведомление', content=layout)
button.bind(on_press=popup.dismiss)
popup.open()

Тоже ничего военного, но не совсем удобно для обычного

MessageBox'а

, правда?

Как бывший Delphiнист, имею дурную привычку вызывать

MessageBox

одной строкой. И в коем-то веке дурная привычка принесла пользу — спустя несколько

десятков

чашек кофе на сцену выходит

XPopup

Главное — вовремя остановиться

Безобидная идея упростить себе жизнь со всплывающими сообщениями в итоге выросла в целый пакет, который с удовольствием был

отжат

включен командой разработчиков в пакет расширений фреймворка.

Для сравнения — вышеописанная задача с кнопкой реализуется следующим образом:

XNotifyBase(title='Получено новое сообщение!', text='Что будем делать?',
            buttons=['Открыть', 'Пометить прочитанным', 'Напомнить позже'])

Но пойдем по порядку. Иерархия классов пакета выглядит так:

Popup

Создаем удобства

Примечание.

В этой статье будут рассмотрены классы уведомлений (

XNotifyBase

и его потомки). Подробнее об остальных классах — в следующей статье.

Класс XNotification

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

XNotification(text='Это окно закроется через 3 секунды', show_time=3)

Если

show_time

не указывать — окно будет закрыто только при вызове метода

.dismiss()

.

Класс XMessage

Аналог привычного

MessageBox

, т.е. окно, имеющее заголовок (title), некое сообщение (text) и кнопку «Ok». Пример:

XMessage(text='Некое сообщение', title='Заголовок')

Стандартная подпись кнопки легко меняется на любую другую:

XMessage(text='Некое сообщение', title='Заголовок', buttons=['Закрыть'])

Также просто заменяется набор отображаемых кнопок:

XMessage(text='Некое сообщение', title='Заголовок', buttons=['Закрыть', 'Напомнить позже'])

О том, как обработать нажатие кнопки — будет рассказано ниже.

Класс XError

По сути — тот же

XMessage

. Разница в том, что данный класс задает заголовок по умолчанию (т.е.

title

можно не указывать):

XError(text='Произошла сферическая ошибка в вакууме')

Не нравится стандартный заголовок — задаем свой:

XError(text='Произошла сферическая ошибка в вакууме', title='Что-то пошло не так...')

Чтобы постоянно не указывать

title

, делаем следующее:

class MyError(XError):
    buttons = ListProperty(['Закрыть'])
    title = StringProperty('Что-то пошло не так...')

MyError(text='Произошла сферическая ошибка в вакууме')

Класс XConfirmation

Всплывающее окно с заголовком «Confirmation» и кнопками «Yes» и «No». Удобно использовать в случаях, когда от пользователя необходимо получить подтверждение («Yes») какого-либо действия или запрет («No») на выполнение данного действия.

Для начала нам потребуется обработчик нажатия кнопки:

def my_callback(instance):
    # Метод класса XConfirmation, возвращает True, если была нажата кнопка "Yes"
    if instance.is_confirmed():
        print('Вы согласились')
    else:
        print('Вы отказались')

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

XConfirmation(text='Необходимо подтверждение действия. Вы согласны?', on_dismiss=my_callback)

Опять же, стандартные кнопки можно заменить своими. Но в таком случае перестанет работать метод

.is_confirmed()

, так как он ориентируется на нажатие кнопки «Yes». Это легко решается путем использования свойства

.button_pressed

, хранящим название нажатой кнопки. Внесем изменения в наш обработчик:

def my_callback(instance):
    # Свойство доступно всем потомкам XBase
    if instance.button_pressed == 'Подтвердить':
        print('Вы согласились')
    else:
        print('Вы отказались')

Теперь смело можно создавать окно со своим набором кнопок:

XConfirmation(
    text='Необходимо подтверждение действия. Вы согласны?',
    on_dismiss=my_callback, buttons=['Подтвердить', 'Отказать'])

Класс XProgress

Всплывающее окно с индикатором прогресса и кнопкой «Cancel» (заголовок и сообщение — в комплекте). Для управления индикатором будем использовать следующие свойства:

  • value — текущее состояние прогресса
  • max — максимальное значение прогресса (по умолчанию, max=100)

Пример:

popup = XProgress(value=100, max=1000, text='Идет обработка запроса...', title='Ожидайте', buttons=[])

Данный код отобразит всплывающее окно без кнопок, с 10% выполненного прогресса. Дальнейшее изменение прогресса возможно двумя способами.

Способ 1-й — посредством свойства

.value

:

# просто указываем новое значение прогресса
popup.value = 20

Способ 2-й — используем метод

.inc()

:

# увеличиваем текущий прогресс на 1 единицу
popup.inc()
# увеличиваем текущий прогресс на 10 единиц
popup.inc(10)

Особенность использования метода

.inc()

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

Пример:

# Создаем окно и устанавливаем 90% прогресса
popup = XProgress(value=90, text='Идет обработка запроса...', title='Ожидайте')
# Добавляем 15 - теперь индикатор отображает 5%
popup.inc(15)

Этот метод очень удобно использовать в случаях, когда заранее неизвестен максимум или количество выполняемых итераций.

Наряду с методом

.inc()

будет полезен метод

.complete()

. Данный метод выполняет следующее:

  • устанавливает прогресс в максимальное значение
  • заменяет имеющееся сообщение на «Complete»
  • прячет кнопки (если они есть)
  • автоматически закрывает окно через 2 секунды

Класс XNotifyBase

Вышеописанных классов может не хватить на все случаи жизни. Не беда — берем за основу

XNotifyBase

и рисуем все, что душе угодно. Данный класс задает объекту следующее поведение:

  • добавляет во всплывающее окно метку (kivy.uix.label.Label) для отображения сообщения
  • содержит свойство для управления данной меткой (.text)

Свойство

.buttons

наследуется от предка

XBase

, но об этом позже.

Оперируя имеющимися свойствами, можно создать свое собственное уведомление для одноразового использования:

XNotifyBase(title='Получено новое сообщение!', text='Что будем делать?',
            buttons=['Открыть', 'Пометить прочитанным', 'Напомнить позже'])

или для многократного:

class NotifyNewMail(XNotifyBase):
    buttons = ListProperty(['Открыть', 'Пометить прочитанным', 'Напомнить позже'])
    title = StringProperty('Получено новое сообщение!')
    text = StringProperty('Что будем делать?')
popup = NotifyNewMail()

Осталось описать свой обработчик нажатия кнопки — и можно наслаждаться полученным результатом.

Послесловие

Наглядное пособие (видео демонстрацию) можно посмотреть

здесь

.

Скачать пакет XPopup —

здесь

.

Приятного всем кодинга.






Разместим вашу рекламу

Пиши: mail@pythondigest.ru

Нашли опечатку?

Выделите фрагмент и отправьте нажатием Ctrl+Enter.

Система Orphus