These funny little animals
Not so long ago, I was faced with the task in short deadlines to write a working prototype of a GUI application that, without an extra line of code, would be good friends with both Windows and OS X. The choice fell on the
Kivy snake framework, which easily solved the above. And also, in the basic configuration had all the necessary tools for implementing the application.
Well ... almost all. Under the cut, I'll tell you what's wrong and how to overcome it.
Hedgehog Kiwi - a proud bird
The framework has a useful class,
kivy.uix.popup.Popup, for implementing pop-up windows. I will not go into the details of what he can do - the article is not about that. Who is curious - by reference you can read the documentation of this class and its ancestor -
kivy.uix.modalview.ModalView .
But there are nuances. Suppose you are faced with a trivial task - to display a text message in a pop-up window.
Popup allows you to do this quite simply, in one line:
')
Popup(title='', content=Label(text=' ')).open()
Let's complicate the task a bit - add a button, by clicking on which the pop-up window should close:
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()
Also nothing military, but not quite convenient for a regular
MessageBox , right?
As a former Delphist, I have the bad habit of calling
MessageBox on one line. And in some century, a bad habit has benefited - after a few
dozen cups of coffee
XPopup comes on the scene
The main thing is to stop in time
Harmless idea to simplify your life with pop-up messages eventually grew into a whole package, which was happy to be
turned on by the development team in the framework extension package.
For comparison, the above task with a button is implemented as follows:
XNotifyBase(title=' !', text=' ?', buttons=['', ' ', ' '])
But let's go in order. The class hierarchy of a package looks like this:
Popup
We create convenience
Note. This article will discuss the classes of notifications (
XNotifyBase and its descendants). More on the other classes -
in the next article .
XNotification class
Pop-up window with title and text, no buttons. Its feature is the ability to automatically close after a specified number of seconds:
XNotification(text=' 3 ', show_time=3)
If
show_time is not specified, the window will be closed only by calling the
.dismiss () method.
XMessage class
Analogue of the usual
MessageBox , i.e. a window that has a title (title), a kind of message (text) and the "Ok" button. Example:
XMessage(text=' ', title='')
The standard button signature easily changes to any other:
XMessage(text=' ', title='', buttons=[''])
It also simply replaces the set of buttons displayed:
XMessage(text=' ', title='', buttons=['', ' '])
How to handle a button click - will be discussed below.
Class xrorror
In fact - the same
XMessage . The difference is that this class sets the default
title (that is, you can leave out the
title ):
XError(text=' ')
I do not like the standard title - we set our own:
XError(text=' ', title='- ...')
In order not to constantly indicate the
title , do the following:
class MyError(XError): buttons = ListProperty(['']) title = StringProperty('- ...') MyError(text=' ')
XConfirmation class
A pop-up window with the title “Confirmation” and the buttons “Yes” and “No”. It is convenient to use in cases where it is necessary to obtain confirmation (“Yes”) of an action or prohibition (“No”) from the user to perform this action.
First we need a handler for the event of closing the dialog:
def my_callback(instance):
After the handler is written, you can create a pop-up window:
XConfirmation(text=' . ?', on_dismiss=my_callback)
Again, you can replace the standard buttons with your own. But in this case, the
.is_confirmed () method will stop working, since it focuses on pressing the “Yes” button. This is easily solved by using the
.button_pressed property, which stores the name of the pressed button. We make changes to our handler:
def my_callback(instance):
Now you can safely create a window with your own set of buttons:
XConfirmation( text=' . ?', on_dismiss=my_callback, buttons=['', ''])
XProgress class
A pop-up window with a progress indicator and a “Cancel” button (header and message are included). To control the indicator we will use the following properties:
- value - the current state of progress
- max - the maximum value of progress (by default, max = 100)
Example:
popup = XProgress(value=100, max=1000, text=' ...', title='', buttons=[])
This code will display a pop-up window without buttons, with 10% of the progress made. Further change in progress is possible in two ways.
Method 1 is using the
.value property:
Method 2 — use the
.inc () method:
The peculiarity of using the
.inc () method is that when the maximum value of progress is reached, the indicator does not stop at the maximum, but a “looping” occurs, i.e. Progress is reset and the countdown starts from scratch.
Example:
This method is very useful in cases where the maximum or the number of iterations performed is not known in advance.
Along with the
.inc () method, the
.complete () method will be useful. This method does the following:
- sets progress to maximum
- replaces the existing message with “Complete”
- hides buttons (if any)
- automatically closes the window after 2 seconds
Class XNotifyBase
The above classes may not be enough for all occasions. It does not matter - we take
XNotifyBase as a basis and draw everything your heart desires. This class gives the object the following behavior:
- adds a label to the popup window ( kivy.uix.label.Label ) to display the message
- contains property for managing this label ( .text )
The
.buttons property
is inherited from the
XBase ancestor, but more on that later.
Using the available properties, you can create your own single-use notification:
XNotifyBase(title=' !', text=' ?', buttons=['', ' ', ' '])
or for multiple:
class NotifyNewMail(XNotifyBase): buttons = ListProperty(['', ' ', ' ']) title = StringProperty(' !') text = StringProperty(' ?') popup = NotifyNewMail()
It remains to describe your handler for the event of closing the dialog - and you can enjoy the result.
Afterword
A visual aid (video demonstration) can be viewed
here .
Download XPopup package -
here .
Enjoy all coding.