[英]Kivy: Custom button not updating with self.state change
我正在尝试创建一个 GUI,在查看了这里的各种帖子后,我仍然感到困惑。 我的问题是,当我将self.state
设置为不同的东西时,我用来反映 GPIO 按钮状态的自定义按钮没有更新其外观。 我认为它可能与对象构造有关,但我不知道如何修复它。
import kivy
kivy.require('1.11.1')
from kivy.app import App
from kivy.uix.widget import Widget
from kivy.properties import NumericProperty, ObjectProperty
from kivy.uix.floatlayout import FloatLayout
from kivy.uix.button import Button
from kivy.clock import Clock
from kivy.core.window import Window
import RPi.GPIO as GPIO
# make app run in fullscreen mode
Window.fullscreen = 'auto' # uses display's current resolution
# Set up GPIO
ok_btn_pin = 4
GPIO.setmode(GPIO.BCM)
GPIO.setup(ok_btn_pin, GPIO.IN, pull_up_down=GPIO.PUD_DOWN)
GPIO.add_event_detect(ok_btn_pin, GPIO.BOTH) #detect if GPIO.RISING or GPIO.FALLING occur
class GPIOButton(Button):
btn_gpio_pin = NumericProperty(-1)
def __init__(self, **kwargs):
super(GPIOButton, self).__init__(**kwargs)
print("GPIOButton __init__ called")
print("btn_gpio_pin =", self.btn_gpio_pin)
def update(self, dt):
#print("GPIOButton update() called")
if GPIO.input(self.btn_gpio_pin) == GPIO.HIGH and GPIO.event_detected(self.btn_gpio_pin):
self.state = 'down'
print("Pin", self.btn_gpio_pin, self.state)
elif GPIO.input(self.btn_gpio_pin) == GPIO.LOW and GPIO.event_detected(self.btn_gpio_pin):
self.state = 'normal'
print("Pin", self.btn_gpio_pin, self.state)
class LeftSidebar(FloatLayout):
ok_btn = GPIOButton(btn_gpio_pin = ok_btn_pin)
def __init__(self, **kwargs):
super(LeftSidebar, self).__init__(**kwargs)
print("LeftSidebar __init__ called")
def update(self, dt):
#print("LeftSidebar update() called")
self.ok_btn.update(dt)
class LifterGUI(FloatLayout):
left_sidebar = LeftSidebar()
def __init__(self, **kwargs):
super(LifterGUI, self).__init__(**kwargs)
print("LifterGUI __init__ called")
Clock.schedule_interval(self.update, 1.0/10.0)
def update(self, dt):
#print("LifterGUI update() called")
self.left_sidebar.update(dt)
class LifterApp(App):
def build(self):
self.root = LifterGUI()
return self.root
if __name__ == '__main__':
try:
LifterApp().run()
finally:
GPIO.cleanup()
#:kivy 1.11.1
#:set camera_width_percent 4.0/5.0
#:set sidebar_width_percent (1.0 - camera_width_percent) / 2.0
<LeftSidebar>:
ok_btn_button: ok_btn
#:set num_btns 10.0
canvas:
Color:
rgb: 1, 0, 0
Rectangle:
pos: self.pos
size: self.size
GPIOButton:
id: ok_btn
btn_gpio_pin: 4
text: "ok"
size_hint: (1.0, 1.0/num_btns)
pos_hint: {'top': 1.0/num_btns}
<LifterGUI>:
left_sidebar_widget: left_sidebar
LeftSidebar:
id: left_sidebar
size_hint: (sidebar_width_percent, 1.0)
我单击 GPIO 按钮 3 次,这会打印到终端,但不会更新 GPIOButton 外观。 请注意,由于某种原因,LeftSidebar __init__ 和 GPIOButton __init__ 每个都被调用了两次(我认为一次来自我的类属性声明,一次来自 kv 文件,但我不确定)。 我已经尝试使用 ObjectProperty(None) 代替 ok_btn 和 left_sidebar 来查看是否有帮助,但后来我得到了AttributeError: 'NoneType' object has no attribute 'update'
错误,所以我不确定这是正确的方法。
[INFO ] [Logger ] Record log in /home/pi/.kivy/logs/kivy_20-09-30_53.txt
[INFO ] [Kivy ] v1.11.1
[INFO ] [Kivy ] Installed at "/usr/local/lib/python3.7/dist-packages/kivy/__init__.py"
[INFO ] [Python ] v3.7.3 (default, Dec 20 2019, 18:57:59)
[GCC 8.3.0]
[INFO ] [Python ] Interpreter at "/usr/bin/python3"
[INFO ] [Factory ] 184 symbols loaded
[INFO ] [Image ] Providers: img_tex, img_dds, img_sdl2, img_pil, img_gif (img_ffpyplayer ignored)
[INFO ] [Text ] Provider: sdl2(['text_pango'] ignored)
[INFO ] [Window ] Provider: sdl2(['window_egl_rpi'] ignored)
[INFO ] [GL ] Using the "OpenGL" graphics system
[INFO ] [GL ] Backend used <sdl2>
[INFO ] [GL ] OpenGL version <b'3.1 Mesa 19.3.2'>
[INFO ] [GL ] OpenGL vendor <b'VMware, Inc.'>
[INFO ] [GL ] OpenGL renderer <b'llvmpipe (LLVM 9.0.1, 128 bits)'>
[INFO ] [GL ] OpenGL parsed version: 3, 1
[INFO ] [GL ] Shading version <b'1.40'>
[INFO ] [GL ] Texture max size <8192>
[INFO ] [GL ] Texture max units <32>
[INFO ] [Window ] auto add sdl2 input provider
[INFO ] [Window ] virtual keyboard not allowed, single mode, not docked
GPIOButton __init__ called
btn_gpio_pin = 4
LeftSidebar __init__ called
LeftSidebar __init__ called
GPIOButton __init__ called
btn_gpio_pin = -1
LifterGUI __init__ called
[INFO ] [ProbeSysfs ] device match: /dev/input/event0
[INFO ] [MTD ] Read event from </dev/input/event0>
[INFO ] [ProbeSysfs ] device match: /dev/input/event0
[INFO ] [HIDInput ] Read event from </dev/input/event0>
[INFO ] [Base ] Start application main loop
[INFO ] [HIDMotionEvent] using <WaveShare WS170120>
[INFO ] [MTD ] </dev/input/event0> range position X is 0 - 800
[INFO ] [HIDMotionEvent] <WaveShare WS170120> range ABS X position is 0 - 800
[INFO ] [MTD ] </dev/input/event0> range position Y is 0 - 480
[INFO ] [HIDMotionEvent] <WaveShare WS170120> range ABS Y position is 0 - 480
[INFO ] [MTD ] </dev/input/event0> range touch major is 0 - 0
[INFO ] [HIDMotionEvent] <WaveShare WS170120> range ABS pressure is 0 - 255
[INFO ] [MTD ] </dev/input/event0> range touch minor is 0 - 0
[INFO ] [HIDMotionEvent] <WaveShare WS170120> range position X is 0 - 800
[INFO ] [MTD ] </dev/input/event0> range pressure is 0 - 255
[INFO ] [HIDMotionEvent] <WaveShare WS170120> range position Y is 0 - 480
[INFO ] [MTD ] </dev/input/event0> axes invertion: X is 0, Y is 0
[INFO ] [HIDMotionEvent] <WaveShare WS170120> range pressure is 0 - 255
[INFO ] [MTD ] </dev/input/event0> rotation set to 0
[INFO ] [GL ] NPOT texture support is available
Pin 4 down
Pin 4 normal
Pin 4 down
Pin 4 normal
Pin 4 down
Pin 4 normal
GPIOButton
的__init__()
被调用两次。 一旦调用build()
方法并执行self.root = LifterGUI()
。 这将通过kv
规则创建出现在您的 GUI 中的GPIOButton
。 当在LeftSidebar
类中执行ok_btn = GPIOButton(btn_gpio_pin = ok_btn_pin)
时,将再次调用__init__()
方法。 第二个调用创建了一个GPIOButton
实例,该实例未出现在您的 GUI 中,但它是在update()
方法中引用的实例。
由于您已经在kv
设置了对GPIOButton
的引用,您可以修改LeftSidebar
类以使用该引用:
class LeftSidebar(FloatLayout):
ok_btn_button = ObjectProperty(None)
def __init__(self, **kwargs):
super(LeftSidebar, self).__init__(**kwargs)
print("LeftSidebar __init__ called")
def update(self, dt):
#print("LeftSidebar update() called")
self.ok_btn_button.update(dt)
该ok_btn_button
在kv
和ok_btn_button
在LeftSidebar
成立了以参考GPIOButton
是建在kv
。 有了它,您可以在LeftSidebar
类中使用self.ok_btn_button
来引用按钮。
请注意,您的LifterGUI
错误LifterGUI
。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.