Kivy 标签在验证 IP 地址时无法刷新

Kivy Label Unable to refresh when validating the Ip address

我正在用 raspberry pi module.In 用户界面构建一个 Kivy 界面 我有显示 Ip 的状态屏幕 address.If 我断开了以太网电缆,屏幕应该给我error label(kivy screenone label:IpAddress) 并且当我重新连接以太网电缆时,标签应该更新回 IP 地址。不幸的是,当我断开以太网电缆时,应用程序显示 "Error" 但当我重新连接以太网时,它没有显示我的 IP 地址。 Ipaddress 标签保持为 "Error"..

##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

断开以太网电缆之前(看起来不错)

断开电缆后(看起来不错)

重新连接网线后(不好)

看起来代码卡在 除了 OSError: 因为它没有变回以太网地址。

问题

不重置属性,print_ipsocket.create_connection() 调用后 try 块内。

解决方案

class ScreenOne,执行以下操作:

  • stringIP=subprocess.check_output(["hostname", "-I"]).split()[0] 移动到 socket.create_connection() 通话后
  • 将 class 属性 print_ip = StringProperty(str(stringIP).strip("b'")) 替换为 print_ip = StringProperty('')
  • stringIP = subprocess.check() 调用后添加 self.print_ip = str(stringIP).strip("b'")
  • 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 ")

在您设置的 kivy 文件中 id:ipAddress 这意味着标签将查看 ScreenOne 对象的 ipAddress 属性。

由于 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