简体   繁体   中英

how do i continously keep on updating my label in kivy?

I've been stuck on this one for hours now. I'm making a homemade smarthome terminal, and have been tinkering with kivy for about 2 weeks and it's been great so far. I'm at the point where I want to show the temperature inside a label inside a screen. I've made an actionbar with 4 buttons that slides through screens when clicked. In the first screen called "Thermostaat", I want to display a label with a temperature read from another external script I've written. I can't seem to get the temperature inside a label, even with a dummy value' Here's my main.py:

#!/usr/bin/env python3
from kivy.app import App
from kivy.uix.screenmanager import ScreenManager,Screen
from kivy.properties import ObjectProperty, StringProperty
from kivy.uix.boxlayout import BoxLayout
from kivy.clock import Clock
from kivy.uix.label import Label
from kivy.lang import Builder

class Menu(BoxLayout):
    manager = ObjectProperty(None)
    def __init__(self,**kwargs):
        super(Menu, self).__init__(**kwargs)
        Clock.schedule_interval(self.getTemp, 1)
    def getTemp(self,dt):
        thetemp = 55 #will be changed to temp.read()
        self.ids.TempLabel.text = str(thetemp)
        print(thetemp)

class ScreenThermo(Screen):
    pass

class ScreenLight(Screen):
    pass

class ScreenEnergy(Screen):
    pass

class ScreenWeather(Screen):
    pass

class Manager(ScreenManager):
    screen_thermo = ObjectProperty(None)
    screen_light = ObjectProperty(None)
    screen_energy = ObjectProperty(None)
    screen_weather = ObjectProperty(None)

class MenuApp(App):
    def thermostaat(self):
        print("Thermostaat")

    def verlichting(self):
        print("Verlichting")

    def energie(self):
        print("Energie")

    def weer(self):
        print("Het Weer")

    def build(self):
        Builder.load_file("test.kv")
        return Menu()


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

And here's my .kv file:

#:kivy 1.10.0
<Menu>:

    manager: screen_manager
    orientation: "vertical"
    ActionBar:
        size_hint_y: 0.05
        ActionView:
            ActionPrevious:
            ActionButton:
                text: "Thermostaat"
                on_press: root.manager.current= 'thermo'
                on_release: app.thermostaat()
            ActionButton:
                text: "Verlichting"
                #I want my screens to switch when clicking on this actionbar button
                on_press: root.manager.current= 'light'
                on_release: app.verlichting()
            ActionButton:
                text: "Energieverbruik"
                on_press: root.manager.current= 'energy'
                on_release: app.energie()
            ActionButton:
                text: "Het Weer"
                on_press: root.manager.current= 'weather'
                on_release: app.weer()
    Manager:
        id: screen_manager

<ScreenThermo>:
    Label:
        #this is where i want my label that shows the temperature my sensor reads
        text: "stuff1"
<ScreenLight>:
    Button:
        text: "stuff2"
<ScreenEnergy>:
    Button:
        text: "stuff3"
<ScreenWeather>:
    Button:
        text: "stuff4"

<Manager>:
    id: screen_manager
    screen_thermo: screen_thermo
    screen_light: screen_light
    screen_energy: screen_energy
    screen_weather: screen_weather

    ScreenThermo:
        id: screen_thermo
        name: 'thermo'
        manager: screen_manager
    ScreenLight:
        id: screen_light
        name: 'light'
        manager: screen_manager
    ScreenEnergy:
        id: screen_energy
        name: 'energy'
        manager: screen_manager
    ScreenWeather:
        id: screen_weather
        name: 'weather'
        manager: screen_manager

I'm constantly getting the follow error:

super(ObservableDict, self).__getattr__(attr))
 AttributeError: 'super' object has no attribute '__getattr__'

Here's my traceback incase you're wondering:

Traceback (most recent call last):
   File "main.py", line 57, in <module>
     MenuApp().run()
   File "/home/default/kivy/kivy/app.py", line 829, in run
     runTouchApp()
   File "/home/default/kivy/kivy/base.py", line 502, in runTouchApp
     EventLoop.window.mainloop()
   File "/home/default/kivy/kivy/core/window/window_pygame.py", line 403, in mainloop
     self._mainloop()
   File "/home/default/kivy/kivy/core/window/window_pygame.py", line 289, in _mainloop
     EventLoop.idle()
   File "/home/default/kivy/kivy/base.py", line 337, in idle
     Clock.tick()
   File "/home/default/kivy/kivy/clock.py", line 581, in tick
     self._process_events()
   File "kivy/_clock.pyx", line 367, in kivy._clock.CyClockBase._process_events
     cpdef _process_events(self):
   File "kivy/_clock.pyx", line 397, in kivy._clock.CyClockBase._process_events
     raise
   File "kivy/_clock.pyx", line 395, in kivy._clock.CyClockBase._process_events
     event.tick(self._last_tick)
   File "kivy/_clock.pyx", line 167, in kivy._clock.ClockEvent.tick
     ret = callback(self._dt)
   File "main.py", line 17, in getTemp
     self.ids.TempLabel.text = str(thetemp)
   File "kivy/properties.pyx", line 839, in kivy.properties.ObservableDict.__getattr__
     super(ObservableDict, self).__getattr__(attr))
 AttributeError: 'super' object has no attribute '__getattr__'

I hope anyone is willing to help me with this, because I want to continue with this project, I've got most of the functionality of my SmartHome equipment working already, so the last part is to make a decent GUI to fit it all in(controlling the lights, controlling the temperature in the house etc...)

use a StringProperty

<ScreenThermo>:
    Label:
        #this is where i want my label that shows the temperature my sensor reads
        text: root.thermo_text


class ScreenThermo(BoxLayout):
      thermo_text = StringProperty("stuff")

...

then any time you want to seet the text just do

my_screen.thermo_text = "ASD"

there is no id TempLabel in your menu

first thing, you must add the TempLabel in your kv:

...
<ScreenThermo>:
    Label:
        id: TempLabel
        text: "stuff1"
...

then update the right label:

...
class Menu(BoxLayout):
    manager = ObjectProperty(None)
    def __init__(self,**kwargs):
        super(Menu, self).__init__(**kwargs)
        Clock.schedule_interval(self.getTemp, 1)
    def getTemp(self,dt):
        thetemp = 55 #will be changed to temp.read()
        self.manager.screen_thermo.ids.TempLabel.text = str(thetemp)
        print(thetemp)
...

Using ObjectProperty

In the example, I used an ObjectProperty to hook up to the label for temperature because an id is a weakref to the widget. Using an ObjectProperty creates a direct reference, provides faster access and is more explicit.

main.py

1. Import External Script

from temperature import read_temperature

2. Declare ObjectProperty

class ScreenThermo(Screen):
    temperature = ObjectProperty(None)

3. Update Temperature Text

def getTemp(self, dt):
    temp = read_temperature()
    print(temp)
    self.manager.screen_thermo.temperature.text = str(temp)

menu.kv - kv File

4. Hook up ObjectProperty to id

<ScreenThermo>:
    temperature: temperature
    Label:
        id: temperature
        #this is where i want my label that shows the temperature my sensor reads
        text: "stuff1"

temperature.py - Simulator

This is an external script simulating the temperature.

import random


def read_temperature():
    return random.randint(0, 100)

Output

在此处输入图片说明

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM