Texture management in Kivy using atlas
Kivy is an open source, cross-platform Python framework for the development of applications that makes use of innovative, multi-touch user interfaces.
What will you learn in this post?
We will look at how to use atlas files to manage textures in kivy and creating one of our own.
Some resources for you: Atlas: Kivy Documentation, Kivy wiki: Theming Kivy, Oreilly's theming in kivy
What is atlas file?
Atlas manages texture atlases: packing multiple textures into one. With it, you reduce the number of images loaded and speedup the application loading.
An Atlas is composed of 2 or more files:
- a json file (.atlas) that contains the image file names and texture locations of the atlas.
- one or multiple image files containing textures referenced by the .atlas file.
If you want a Material design feel for your application and need theming already taken care for you, then I suggest you to look at KivyMD.
Content
- Creating your own atlas file.
- Let's dive into code.
What do we have? Download the code for this post from here.
What we want.
Creating your own atlas file
Source for theme files: Themes
cd
to the folder where you have all the images you want to create an atlas of then type the following command in the terminal.
python3 -m kivy.atlas myatlas 256x256 *.png
defaulttheme-0.png Red theme Original source
defaulttheme.atlas
{"defaulttheme-0.png": {"progressbar_background": [391, 223, 24, 24], "tab_btn_disabled": [279, 127, 32, 32], "tab_btn_pressed": [381, 127, 32, 32], "image-missing": [249, 167, 48, 48], "splitter_h": [155, 113, 32, 7], "splitter_down": [501, 249, 7, 32], "splitter_disabled_down": [504, 127, 7, 32], "vkeyboard_key_down": [2, 34, 32, 32], "vkeyboard_disabled_key_down": [415, 127, 32, 32], "selector_right": [248, 219, 55, 62], "player-background": [2, 283, 103, 103], "selector_middle": [191, 219, 55, 62], "spinner": [235, 72, 29, 37], "tab_btn_disabled_pressed": [313, 127, 32, 32], "switch-button_disabled": [277, 287, 43, 32], "textinput_disabled_active": [372, 322, 64, 64], "splitter_grip": [499, 189, 12, 26], "vkeyboard_key_normal": [36, 34, 32, 32], "button_disabled": [80, 72, 29, 37], "media-playback-stop": [399, 167, 48, 48], "splitter": [501, 77, 7, 32], "splitter_down_h": [121, 113, 32, 7], "sliderh_background_disabled": [87, 122, 41, 37], "modalview-background": [2, 161, 45, 54], "button": [142, 72, 29, 37], "splitter_disabled": [503, 287, 7, 32], "checkbox_radio_disabled_on": [433, 77, 32, 32], "slider_cursor": [2, 111, 48, 48], "vkeyboard_disabled_background": [68, 217, 64, 64], "checkbox_disabled_on": [297, 77, 32, 32], "sliderv_background_disabled": [2, 68, 37, 41], "button_disabled_pressed": [111, 72, 29, 37], "audio-volume-muted": [199, 167, 48, 48], "close": [417, 227, 20, 20], "action_group_disabled": [468, 462, 33, 48], "vkeyboard_background": [2, 217, 64, 64], "checkbox_off": [331, 77, 32, 32], "tab_disabled": [305, 249, 96, 32], "sliderh_background": [130, 122, 41, 37], "switch-button": [322, 287, 43, 32], "tree_closed": [439, 227, 20, 20], "bubble_btn_pressed": [435, 287, 32, 32], "selector_left": [134, 219, 55, 62], "filechooser_file": [174, 322, 64, 64], "checkbox_radio_disabled_off": [399, 77, 32, 32], "checkbox_radio_on": [211, 127, 32, 32], "checkbox_on": [365, 77, 32, 32], "button_pressed": [173, 72, 29, 37], "audio-volume-high": [49, 167, 48, 48], "audio-volume-low": [99, 167, 48, 48], "progressbar": [305, 223, 32, 24], "previous_normal": [483, 127, 19, 32], "separator": [503, 462, 5, 48], "filechooser_folder": [240, 322, 64, 64], "checkbox_radio_off": [467, 77, 32, 32], "textinput_active": [306, 322, 64, 64], "textinput": [438, 322, 64, 64], "player-play-overlay": [126, 395, 117, 115], "media-playback-pause": [299, 167, 48, 48], "sliderv_background": [41, 68, 37, 41], "ring": [358, 402, 108, 108], "bubble_arrow": [70, 56, 16, 10], "slider_cursor_disabled": [449, 167, 48, 48], "checkbox_disabled_off": [469, 287, 32, 32], "action_group_down": [468, 412, 33, 48], "spinner_disabled": [204, 72, 29, 37], "splitter_disabled_h": [87, 113, 32, 7], "bubble": [107, 321, 65, 65], "media-playback-start": [349, 167, 48, 48], "vkeyboard_disabled_key_normal": [449, 127, 32, 32], "overflow": [245, 127, 32, 32], "tree_opened": [461, 227, 20, 20], "action_item": [339, 223, 24, 24], "bubble_btn": [401, 287, 32, 32], "audio-volume-medium": [149, 167, 48, 48], "action_group": [52, 111, 33, 48], "spinner_pressed": [266, 72, 29, 37], "filechooser_selected": [2, 388, 122, 122], "tab": [403, 249, 96, 32], "action_bar": [173, 123, 36, 36], "action_view": [365, 223, 24, 24], "tab_btn": [347, 127, 32, 32], "switch-background": [192, 287, 83, 32], "splitter_disabled_down_h": [468, 403, 32, 7], "action_item_down": [367, 287, 32, 32], "switch-background_disabled": [107, 287, 83, 32], "textinput_disabled": [245, 399, 111, 111], "splitter_grip_h": [483, 235, 26, 12]}}
Let's dive into the code
After you have run the above command you should have got atleast 2 files a .png
and a .atlas
.
In our example we have 5 files.
Structure
- main.py
- main.kv
- src
- components/
- __init__.py
- CustomButtons.py
- CustomCheckBoxes.py
-textures/
- theme-blue/
...
- myatlas-0.png
- myatlas-1.png
- myatlas-2.png
- myatlas-3.png
- myatlas.atlas
...
- theme-orange/
...
- myatlas-0.png
- myatlas-1.png
- myatlas-2.png
- myatlas-3.png
- myatlas.atlas
...
- red-lightgrey/
...
- myatlas-0.png
- myatlas-1.png
- myatlas-2.png
- myatlas-3.png
- myatlas.atlas
...
let's make some change in our code or you can download it from here.
src/components/CustomButtons.py
from kivy.uix.button import Button
class CustomButton(Button):
def __init__(self, **kwargs):
super().__init__(**kwargs)
# self.background_down = 'atlas://textures/red-lightgrey/myatlas/button_pressed'
self.background_normal = 'atlas://textures/red-lightgrey/myatlas/button_pressed'
src/components/CustomCheckBoxes.py
from kivy.uix.checkbox import CheckBox
class CustomCheckBox(CheckBox):
def __init__(self, **kwargs):
super().__init__(**kwargs)
self.background_down = 'atlas://textures/red-lightgrey/myatlas/button_pressed'
self.background_checkbox_normal = 'atlas://textures/red-lightgrey/myatlas/checkbox_off'
self.background_checkbox_down = 'atlas://textures/red-lightgrey/myatlas/checkbox_on'
self.background_checkbox_disabled_normal = 'atlas://textures/red-lightgrey/myatlas/checkbox_disabled_off'
self.background_checkbox_disabled_down = 'atlas://textures/red-lightgrey/myatlas/checkbox_disabled_on'
In main.kv file add the following code below <Theming>:
class
<ProgressBar>:
canvas:
Color:
rgb: 1, 1, 1
BorderImage:
border: (12, 12, 12, 12)
pos: self.x, self.center_y - 12
size: self.width, 24
source: 'atlas://textures/red-lightgrey/myatlas/progressbar_background'
BorderImage:
border: [int(min(self.width * (self.value / float(self.max)) if self.max else 0, 12))] * 4
pos: self.x, self.center_y - 12
size: self.width * (self.value / float(self.max)) if self.max else 0, 24
source: 'atlas://textures/red-lightgrey/myatlas/progressbar'
and here we have.
Similarly, you can link different atlases to different widgets.
- Button: Red
- CheckBox :Orange
- ProgressBar: Blue
Conslusion
Thank you for reading this post — I hope you found this helpful. You can find me on GitHub, LinkedIn and CodeMentor. If you have any questions, feel free to reach out to me!
More posts:
- Customizing your Navigation Drawer in Kivy & KivyMD
- Plyer: Platform independent compatibility layer
- Texture management in Kivy using atlas
- Beginner Kivy Tutorial: Basic Crash Course for Apps in Kivy
- Redux, Store, Actions, Reducers and logger: Get Started and a little further (1)
- Redux, Reactotron, Actions, Reducers and Sagas (2)