I really want to like Kivy…
I was trying to asyncronously load comic book images out of a cbr
file
(a rar
archive) but was having a hell of a time figuring it out.
Like most things in Kivyland, it wasn't hard after you already know
how. The key is providing a load_callback
and then bind
.
The docs almost
tell you everything you need to know, except they don't say shit
about load_callback
, you need to spelunk through the source
code (look in _load()
) to figure that out.
And then some trial and error to figure out you need to return a
kivy.core.image.Image
and not a kivy.uix.image.Image
because that
wouldn't have saved me a ½ inch of hairline…
The following is paraphrased from my program so it probably won't work exactly as I've typed it here. It's too much work to make full working example. You're welcome.
#:import Page myapp.kvwidgets.Page
<Page>:
orientation: "vertical"
size_hint: None, None
size: 300, 300
canvas.before:
Color:
rgba: 0,0,0,1
Rectangle:
pos: self.pos
size: self.size
ImageButton:
id: image
from kivy.logger import Logger
from kivy.core.image import Image as CoreImage
from kivy.uix.boxlayout import BoxLayout
from kivy.loader import Loader
from io import BytesIO
def rar_loader(self, rarfile, filename):
Logger.debug("rar_loader('%s')", filename)
_, ext = os.path.splitext( filename )
ext = ext[1:].lower()
data = rarfile.open(filename).read()
data = BytesIO(data)
return CoreImage(data, ext=ext, filename=filename)
class Page(BoxLayout):
def __init__(self, rarfile, filename, **kw):
"""
rarfile is a RarFile() object
filename is the path inside the rarfile
"""
super(Page, self).__init__(**kw)
def cb_loaded(proxy_image):
# called when image is finished being loaded
self.ids.image.texture = proxy_image.image.texture
try:
loader_func = functools.partial(rar_loader, rarfile)
proxy_image = Loader.image(filename, load_callback=loader_func)
proxy_image.bind(on_load=cb_loaded)
# show loading image
self.ids.image.texture = proxy_image.texture
except Exception as e:
Logger.error( str(e) )