BPS
BPS

Reputation: 1231

How to immediately update widget in Kivy?

I have this sample program written in Python and Kivy:

#!/usr/bin/env python2.7
# -*- coding: utf-8 -*-

import time
from kivy.app import App
from kivy.core.window import Window
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.image import AsyncImage
from kivy.uix.label import Label


class Application(App):

    def build(self):
        keyboard = Window.request_keyboard(None, self)
        keyboard.bind(on_key_down=self.__on_key_down)

        box_layout = BoxLayout(orientation='vertical')

        self.__label = Label(text='Ready')
        box_layout.add_widget(self.__label)

        self.__img = AsyncImage()
        box_layout.add_widget(self.__img)

        return box_layout

    def __on_key_down(self, keyboard, keycode, text, modifiers):
        self.__set_status('Loading, please wait...')
        print(self.__label.text)
        time.sleep(3) # simulates long image download time
        self.__img.source = 'http://pl.python.org/forum/Smileys/default/cheesy.gif'

    def __set_status(self, text):
        self.__label.text = text
        # self.__label.canvas.ask_update()


app = Application()
app.run()

Basically what I want to do is label which displays status of application like: Ready, loading, done, etc. but my widget is not updating text when it should.

What can I do to immediately update text in self.__label widget?

I've tried ask_update() method but it seems to not work for this case.

Upvotes: 3

Views: 3320

Answers (1)

kitti
kitti

Reputation: 14854

You're blocking Kivy from doing anything when you call time.sleep. Kivy can't update the screen or process input until your function returns control to the main loop.

When you set the source of the AsyncImage, the image will be downloaded in the background without blocking the main loop. This widget is designed to just work automatically. It will display a loading animation until the image is downloaded, so you don't need to show any text.

If you want to show your own loading text, however, you can do so by using Loader directly. It will return a ProxyImage which you can use to determine when the image has loaded:

def __on_key_down(self, keyboard, keycode, text, modifiers):
    self.__set_status('Loading, please wait...')
    proxy = Loader.image('http://pl.python.org/forum/Smileys/default/cheesy.gif')
    proxy.bind(on_load=self.__image_loaded)

def __image_loaded(self, proxy):
    if proxy.image.texture:
        self.__img.texture = proxy.image.texture
        self.__set_status('Done')

Upvotes: 2

Related Questions