Hmerman6006
Hmerman6006

Reputation: 1913

How do I fix ' ValueError: callback must be a callable, got None' on schedule Kivy.clock callback function?

I have a function that uses the plyer.facades.Wifi library to check the wifi status. The function changes a BooleanProperty variable is_wifi to True or False depending on the status of the wifi. The BooleanProperty variable is binded in the Kv-Language script to an ActionLabel which changes the image depending on the status. The function is then scheduled using Kivy's Clock.schedule_interval().

Problem

The main problem is I am getting a ValueError: callback must be a callable, got None when I schedule the function callback.

I have tried: 1] scheduling the function on initialisation. 2] Calling the scheduling event after initialisation when the user sign in.

Code sample of the imports and function that is called

from plyer import wifi
from kivy.app import App
from kivy.lang import Builder
from kivy.clock import Clock

class TheLogger(FloatLayout):
    is_wifi = BooleanProperty(wifi.is_enabled())
    def __init__(self, **kwargs):
        super().__init__(**kwargs)

    def wifi_is_enabled(self): #Scheduling a callback of this function
        print('checking connection')
        try:
            if wifi.is_enabled():
                self.is_wifi = True
            else:
                self.is_wifi = False
        except OSError:
            pass
class LoginApp(App):
    title = 'Login'
    def build(self):
        self.icon = 'sign_in_5243564.png'
        rt = TheLogger()
        Clock.schedule_interval(rt.wifi_is_enabled(), 0.5) #scheduling callback of wifi_is_enabled() function
        return rt

Kivy language sample that shows binding on the ActionLabel

Builder.load_string('''
<TheLogger>:
    un_input: user_in
    ScreenManager:
        id: _screen_manager
        Screen:
            name: 'choice'
            ActionBar:
                pos_hint: {'top': 1, 'right': 1}
                canvas:
                    Color:
                        rgba: (0,0.4,0.51,1)
                    Rectangle:
                        pos: self.pos
                        size: self.size
                ActionView:
                    use_separator: True
                    ActionPrevious:
                        title: "Sign Out"
                        with_previous: True
                        app_icon: ''
                        color: (1,1,1,1)
                        on_release: app.root.sign_out()
                    ActionLabel: #ActionLabel source with If else block code on callback
                        text: ''
                        Image:
                            source: 'green_wifi_connected_5456.png' if root.is_wifi else 'red_ic_signal_wifi_off_48px_352130.png'
                            center_y: self.parent.center_y
                            center_x: self.parent.center_x
                            size: self.parent.width /1, self.parent.height/ 1
                            allow_stretch: True
''')

Expected result

I want the function to schedule a callback without errors.

Upvotes: 3

Views: 7362

Answers (1)

inclement
inclement

Reputation: 29478

Clock.schedule_interval(rt.wifi_is_enabled(), 0.5)

This code is equivalent to:

callback = rt.wifi_is_enabled()
Clock.schedule_interval(callback, 0.5)

Do you see the problem now? The value of callback is None, which is what you try to schedule.

You need to schedule the function itself, not its return value:

Clock.schedule_interval(rt.wifi_is_enabled, 0.5)

Note that the function will automatically receive a positional argument containing the time since last run/scheduled. Your function will need to accept this argument, even if it ignores it.

Upvotes: 8

Related Questions