Ярлык Kivy не может обновиться при проверке IP-адреса

#python #python-3.x #kivy #kivy-language

#python #python-3.x #kivy #kivy-language

Вопрос:

Я создаю интерфейс Kivy с модулем Raspberry pi.В пользовательском интерфейсе у меня есть экран состояния, на котором отображается IP-адрес.Если я отсоединю кабель Ethernet, экран, предположительно, выдаст мне ярлык ошибки (ярлык kivy screenone: IPAddress), и когда я повторно подключу кабель Ethernet, ярлык должен быть обновлен до Ip-адреса. К сожалению, когда я отключаю кабель Ethernet, приложение показывает «Ошибку», но когда я повторно подключаю Ethernet, он не отображает мой IP-адрес. Метка Ipaddress остается как «Ошибка»..

 ##this is the root widget
class Menu(BoxLayout):
    manager = ObjectProperty(None)

    def __init__(self, **kwargs):
        super(Menu, self).__init__(**kwargs)
        Window.bind(on_keyboard=self._key_handler)
        #btn1 = ActionButton(text='',icon='./assest/usb.jpg')

    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.direction = 'left'
            self.manager.transition = SwapTransition()


class ScreenOne(Screen,BoxLayout):

    stringIP=subprocess.check_output(["hostname", "-I"]).split()[0]
    print_ip = StringProperty(str(stringIP).strip("b'"))

    def __init__(self, **kwargs):
        super(ScreenEnergy, self).__init__(**kwargs)
        #Clock.schedule_interval(self.update_ip, 1)
        scheduler1 = BackgroundScheduler()
        scheduler1.add_job(self.update_ip, 'interval', seconds=1)
        scheduler1.start()
        # #self.update_ip()
        print("status window")


    def update_ip(self,*args):     
        try:
            # connect to the host -- tells us if the host is actually
            # reachable
            socket.create_connection(("www.google.com", 80))
            self.print_ip
            print("ip")
            #print("connected")
            return True
        except OSError:
            self.ids.ipAddress.text="[b][color=ff0000]Error[/color][/b]"
            print("not Ip ")
        return False

        # try:
        #     #socket.inet_aton(self.print_ip)
        #     #socket.inet_pton(socket.AF_INET6, self.print_ip)
        #     self.print_ip='b(([1-9][0-9]?|1[0-9][0-9]|2[0-4][0-9]|25[0-5]).){3}'
        #     self.ids.ipLabel.text="faffxga"
        #         # legal
        # except socket.error:
        #     self.ids.ipLabel.text="adadadsadsa"
        # return False

        #         # Not legal

       class MenuApp(FlatApp):


    def build(self):
        my_callback=Menu()
        #ip_call =ScreenEnergy()
        scheduler = BackgroundScheduler()
        scheduler.add_job(my_callback.is_connected, 'interval', seconds=1)
        #scheduler.add_job(ip_call.update_ip, 'interval', seconds=1)
        scheduler.start()
        return my_callback



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:

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

    Manager:
        id: screen_manager

<ScreenOne>:
    BoxLayout:
        orientation: 'vertical'
        WrappedLabel:
            id:welcomeStatus
            text: "[b]Status[/b]"
            font_size:min(root.width,root.height)/15
        GridLayout:
            cols:2
            row: 3
            padding:root.width*.02,root.height*.03
            spacing:min(root.width,root.height)*.02
            Label:   
                id:ipLabel
                size_hint_x: .15
                color: 0, 0, 0, 1
                text: '[b]IP Address :[/b]'
                markup:True 
            Label:
                id:ipAddress
                size_hint_x: .15
                color: 0, 0, 0, 1
                text: root.print_ip
                color: 1, 0, 0, 1
                bold:True
                markup:True  

<Screen 2>:

<Manager>:

    id: screen_manager
  

ОБНОВЛЕНИЕ ДВА:
После внесения необходимых изменений в код на терминале больше нет ошибок .. по крайней мере, это хороший знак!

 class ScreenOne(Screen,BoxLayout):
    print_ip = StringProperty('')
       
    def __init__(self, **kwargs):
        super(ScreenEnergy, self).__init__(**kwargs)
        Clock.schedule_interval(self.update_ip, 1)
        print("status window")
        
    
    def update_ip(self,*args):     
        try:
            # connect to the host -- tells us if the host is actually
            # reachable
            socket.create_connection(("www.google.com", 80))
            stringIP = subprocess.check_output(["hostname", "-I"]).split()[0]
            self.print_ip = str(stringIP).strip("b'")
            print("ip={self.print_ip}")
            return True
        except OSError:
            self.ids.ipAddress.text="[b][color=ff0000]Error[/color][/b]"
            print("not Ip ")
        return False  

перед отключением кабеля Ethernet (выглядит хорошо) введите описание изображения здесь

после отсоединения кабеля (выглядит хорошо) введите описание изображения здесь

после повторного подключения кабеля Ethernet (не работает) введите описание изображения здесь

похоже, что код застрял, за исключением OSError: потому что он не возвращается к адресу Ethernet.

Ответ №1:

Проблема

Не сброс атрибута print_ip внутри try блока после socket.create_connection() вызова.

Решение

В class ScreenOne , выполните следующие действия:

  • Перейти stringIP=subprocess.check_output(["hostname", "-I"]).split()[0] к после socket.create_connection() вызова
  • Замените атрибут класса print_ip = StringProperty(str(stringIP).strip("b'")) на print_ip = StringProperty('')
  • Добавить self.print_ip = str(stringIP).strip("b'") после stringIP = subprocess.check() вызова
  • Заменить self.ids.ipAddress.text на self.print_ip

Фрагменты

 class ScreenOne(Screen):

    print_ip = StringProperty('')
    ...

    def update_ip(self,*args):     
        try:
            # connect to the host -- tells us if the host is actually
            # reachable
            socket.create_connection(("www.google.com", 80))
            stringIP = subprocess.check_output(["hostname", "-I"]).split()[0]
            self.print_ip = str(stringIP).strip("b'")
            print(f"ip={self.print_ip}")
        except OSError:
            self.print_ip = "[b][color=ff0000]Error[/color][/b]"
            print("not Ip ")
  

Комментарии:

1. Добавьте stringIP = subprocess.check_output(["hostname", "-I"]).split()[0] между socket.create_connection(...) и self.print_ip = str(...) . Пожалуйста, обратитесь к обновленному сообщению для получения подробной информации.

2. Привет, иколим, пожалуйста, проверьте два обновления, которые я добавляю в поле вопроса, если сможете!! приветствия!!

3. Заменить self.ids.ipAddress.text = ... на self.print_ip = ... in except OSError: block. Также удалите return True и return False .

4. Это работает иколим!!!! это работает!! Спасибо!!! Я не изменил * кроме OSError: self.print_ip *, как вы сказали!!

Ответ №2:

В файле kivy, который вы устанавливаете id:ipAddress , это означает, что метка будет просматривать ipAddress свойство ScreenOne объекта.

Из-за того, как работают свойства Kivy, любые изменения этого свойства будут автоматически отражены в метке. Таким образом, в коде python вы не должны устанавливать текст метки напрямую; вместо этого используйте self.ipAddress.set("The New Value")

Вы также не сбрасываете значение метки после ошибки, поэтому даже после установления соединения в инструкции try метка останется со значением ошибки.

Я рекомендую изменить функцию update_ip на это:

 def update_ip(self,*args):     
    try:
        # connect to the host -- tells us if the host is actually
        # reachable
        socket.create_connection(("www.google.com", 80))
        self.print_ip.set(str(stringIP).strip("b'"))
        print("ip")
        #print("connected")
        return True
    except OSError:
        self.print_ip.set("[b][color=ff0000]Error[/color][/b]")
        print("not Ip ")
    return False