【发布时间】:2020-06-12 07:20:32
【问题描述】:
我正在尝试将实例化的导入外部类中的属性绑定到 kivy 类,但它不起作用,我在 kivy 文档或其他地方找不到我的特定案例场景。
我做了一个示例 kivy gui,左侧的标签绑定到 kivy 类属性,当计数器启动时,左侧的标签会相应更新,但右侧的标签绑定到其他类的属性在 kivy "on_start" 方法中进行实例化,当右侧的计数器启动时,您可以在控制台中看到右侧实例化类的属性正在发生变化,但右侧的标签没有变化。
这里的代码很简单,“开始计数器”按钮调用是一个方法,该方法又使用线程调用计数器方法以避免冻结 gui,计数器方法使用 while 循环递增一个数字,因为数字会发生变化左边的标签。带“external”关键字的方法是指右边的导入类计数器,所以和左边的一样,右边的“启动计数器”按钮调用“start_external_counter”方法,在实例化的实例中启动计数器导入的类,导入的类中的数字属性是递增的,但是kivy中的绑定对导入的类属性不起作用,这是我希望解决的问题,如何从外部类或导入的模块中绑定属性到kivy环境。
注意:我可以通过使用带有轮询循环的时钟来更新右侧的标签,每个间隔调用外部类属性,但我认为这不是正确的方法。
提前感谢您的帮助。
from kivy.app import App
from kivy.lang import Builder
from kivy.properties import ObjectProperty, NumericProperty
import time
import threading
kv = '''
BoxLayout:
padding: 40
spacing: 50
# -- INTERNAL CLASS COUNTER --#
BoxLayout:
orientation: 'vertical'
spacing: 50
Label:
text: 'Kivy class attribute binding'
font_size: 30
size: self.texture_size
size_hint_y: .2
Label:
id: counter_label
text: '0'
font_size: 200
size: self.texture_size
BoxLayout:
size_hint_y: None
height: 80
Button:
text: 'Start Counter'
font_size: 30
on_release: app.get_running_app().start_counter()
Button:
text: 'Stop Counter'
font_size: 30
on_release: app.get_running_app().stop_counter()
# -- EXTERNAL CLASS COUNTER -- #
BoxLayout:
orientation: 'vertical'
spacing: 50
Label:
text: 'External class attribute binding'
font_size: 30
size: self.texture_size
size_hint_y: .2
Label:
id: external_counter_label
text: '0'
font_size: 200
size: self.texture_size
BoxLayout:
size_hint_y: None
height: 80
Button:
text: 'Start Counter'
font_size: 30
on_release: app.get_running_app().start_external_counter()
Button:
text: 'Stop Counter'
font_size: 30
on_release: app.get_running_app().stop_external_counter()
'''
class MyClass:
number = 0
stop = False
def count(self):
while not self.stop:
self.number += 1
print 'External counter: %s' % self.number
time.sleep(1)
self.stop = False
class main(App):
number = NumericProperty(0)
external_number = NumericProperty(0)
external_counter = ObjectProperty()
stop = False
def build(self, *args):
layout = Builder.load_string(kv)
return layout
def on_start(self):
root = self.root_window
self.layout = root.children[0]
self.counter_label = self.layout.ids['counter_label']
self.bind(number=self.update_label)
## -- Trying to bind a property
## -- from other non kivy class
self.external_counter_label = self.layout.ids['external_counter_label']
self.external_counter = MyClass()
self.external_number = self.external_counter.number
self.bind(external_number=self.update_external_label)
def update_label(self, *args):
self.counter_label.text = str(self.number)
def start_counter(self):
''' using a thread to start counter
without freezing gui
'''
t = threading.Thread(target=self.count)
t.setDaemon(True)
t.start()
def count(self):
while not self.stop:
self.number += 1
time.sleep(1)
self.stop = False
def stop_counter(self):
self.stop = True
## --- CALLING THE EXTERNAL CLASS METHODS -- ##
def update_external_label(self):
self.external_counter_label.text = self.external_number
def start_external_counter(self):
''' using a thread to start counter
without freezing gui
'''
t = threading.Thread(target=self.external_count)
t.setDaemon(True)
t.start()
def external_count(self):
self.external_counter.count()
def stop_external_counter(self):
self.external_counter.stop = True
if __name__ == '__main__':
main().run()
【问题讨论】:
标签: python attributes kivy bind