Search code examples
pythonpython-3.xkivykivy-language

Kivy Action button unable to update the icon through python


I'm making an app using python and Raspberry pi & wanted to indicate using a icon on action bar if the app connected to internet.In the build method,it's continuously checking if the app connected to internet via " Clock.schedule_interval(my_callback.is_connected, 0.5)" by calling "is_connected". But I don't no how to change the icon if it is connected inside the is_connected method.

class Menu(BoxLayout):
    manager = ObjectProperty(None)
    motorBtn = StringProperty()

    def __init__(self, **kwargs):
        super(Menu, self).__init__(**kwargs)
        Window.bind(on_keyboard=self._key_handler)


    def _key_handler(self, instance, key, *args):
        if key is 27:
            self.set_previous_screen()
            return True

    def set_previous_screen(self):
        if self.manager.current != 'home':
            self.manager.transition = SwapTransition()
            self.manager.current = 'home'
    def btn_SwipeSound(self):
        sound = SoundLoader.load('./assest/arrow.wav')
        if sound:

    def is_connected(self,*args):
        motorBtn = StringProperty()
        index = NumericProperty(-1) 

        try:
            # connect to the host -- tells us if the host is actually
            # reachable
            socket.create_connection(("www.google.com", 80))
            self.motorBtn.icon = './assest/usb.jpg

            print ("connected")
            return True  
        except OSError:
            pass
    self.motorBtn.icon = './assest/usb1.jpg
        print("not connected")
        return False


class MenuApp(FlatApp):
    index = NumericProperty(-1) 

    def build(self):
        my_callback=Menu()
        Clock.schedule_interval(my_callback.is_connected, 0.5)
        return Menu()


if __name__ == '__main__':
    MenuApp().run()

#:kivy 1.10.0
#:import hex kivy.utils.get_color_from_hex
#:import Factory kivy.factory.Factory

<Menu>:
    canvas.before:
        Rectangle:
            pos: self.pos
            size: self.size

    manager: screen_manager
    orientation: "vertical"
    ActionBar:

        size_hint_y: 0.15
        background_image: ''
        background_color: 0.349, 0.584, 0.917, 1
        ActionView:
            ActionPrevious:
                id: actprev
                title: "[b]RheoSb[/b]"
                markup: True
                ##color: 0.105, 0.109, 0.113,1
                font_size: 100
                app_icon: './assest/viclink2.jpg'
                with_previous: False
                on_press: root.set_previous_screen()
                on_press: root.btn_SwipeSound()

            ActionButton:
                id:motorBtn
                text:''
                icon:'./assest/Ethernet.jpg'

    Manager:
        id: screen_manager

<Screen 1>:

<Screen 2>:

<Screen 3>:

<Manager>:

    id: screen_manager

Solution

  • Problem 1 - Double instances of Menu()

    When your app runs, there are two instances of class Menu() created. The first instance is created by my_callback = Menu(). The second instance is created by return Menu(). The first instance does not has a modal view associated to it. On top of that, the clock event is scheduled against the first instance. Due to this, you won't be able to update the icon.

    Solution

    def build(self):
        my_callback = Menu()
        Clock.schedule_interval(my_callback.is_connected, 0.5)
        return my_callback
    

    Problem 2 - Update ActionButton's icon

    The problem was due to incorrect reference / access to ActionButton.

    Solution

    Use self.ids.motorBtn.icon

    def is_connected(self, *args):
        motorBtn = StringProperty()
        index = NumericProperty(-1)
    
        try:
            # connect to the host -- tells us if the host is actually
            # reachable
            socket.create_connection(("www.google.com", 80))
            self.ids.motorBtn.icon = './assest/usb.jpg'
    
            print("connected")
            return True
        except OSError:
            pass
        self.ids.motorBtn.icon = './assest/usb1.jpg'
        print("not connected")
        return False