Python 2.7 引用.kv文件中的类属性

Python 2.7 引用.kv文件中的类属性,python-2.7,kivy,Python 2.7,Kivy,我的.py和.kv文件中有以下相关部分 class DrillScreen(Screen): def __init__(self, **kwargs): super(DrillScreen, self).__init__(**kwargs) self.thedrill = drill(kwargs['options']) self.thedrill.bind(on_answer = self.printtest) def pri

我的.py和.kv文件中有以下相关部分

class DrillScreen(Screen):
    def __init__(self, **kwargs):
        super(DrillScreen, self).__init__(**kwargs)
        self.thedrill = drill(kwargs['options'])
        self.thedrill.bind(on_answer = self.printtest)


    def printtest(self,*args):
        self.ids.answerlabel.text = self.thedrill.answer
        print(self.ids.answerlabel.text)

    def startdrill(self):
        Process(target=self.thedrill.run).start()

对.kv文件的唯一更改是标签文本指向
root.answer
。当我运行此操作时,(并单击.kv中调用
startdrill()
)的按钮,
drill
定期发送其
on_answer
事件,我还单击新创建的按钮手动调用
printtest
,在终端中生成这样的输出:

('This is printtest(): ', 'ti')
('This is printtest(): ', 're')
('This is printtest(): ', 'Default')
('This is printtest(): ', 'Default')
('This is printtest(): ', 'so')
('This is printtest(): ', 'Default')
('This is printtest(): ', 'le')
('This is printtest(): ', 'Default')
带音节的行是
的回复
的结果,带“Default”的行是点击按钮的结果。我无法想象会有什么影响。在检查
钻取
类时,我看不出它有理由立即恢复到以前的值(它实际上在设置
行之后的行上执行
睡眠(1)
。回答
并调度事件)。也许我遗漏了什么,如果没有更合理的解释,我可以发布代码

EDIT2: 下面是一个可运行的示例。 .kv文件:

<DrillScreen>:
    FloatLayout:
        FloatLayout:
            id: wheelbox
            size_hint: 1.0, None
            height: self.width
            pos_hint: {'center_x':0.5,'center_y':0.5}
            background_color: 1,1,1,1
            pos: 0, 200
            Label:
                id: answerlabel
                pos_hint: {'center_x':0.5, 'center_y':0.5}
                text: root.answer
        Button:
            text: 'Start'
            size_hint: 0.5, 0.1
            on_release: root.startdrill()
单击“开始”按钮将启动Drill.run,并在其自己的进程中运行,每秒向终端发送随机数,在运行时,单击printtest()按钮将“Default”作为标签文本值输出。样本输出:

('This is printtest(): ', '8')
('This is printtest(): ', '60')
('This is printtest(): ', '6')
('This is printtest(): ', 'Default')
('This is printtest(): ', '66')
('This is printtest(): ', '68')
('This is printtest(): ', 'Default')
('This is printtest(): ', '89')
('This is printtest(): ', '69')

您需要更改初始化函数中的顺序:

thedrill = ObjectProperty(None) # not really needed ... 

def __init__(self, **kwargs):
    self.thedrill = drill(kwargs['options'])
    self.thedrill.bind(on_answer = self.printtest)
    super(DrillScreen, self).__init__(**kwargs) # this will trigger the kv file section that exploded before ... 
也就是说,使用进程将不适用于您的示例,因为每个进程都有自己的内存,无法直接处理UI。您应该使用进程队列或移动到线程。只需记住从主线程更新UI。(使用时钟@mainthread


玩得开心

没有属性
投诉消失,但即使
printtest()
语句将正确的值打印到终端,外观上的标签也不会更新。我还尝试使用
answer=StringProperty(“”)
,给出标签
root.answer
,并直接在
printest
定义设置
self.answer
中使用。它只是从我初始化的
答案开始,从不改变。另外,如果我将其初始化为,在
def\uuuu init\uuuu
之前说“test”,但在
super
之前将其设置为
self.answer=self.drill.answer
。同样的语句在
printtest
中失败。Galazner我包括一个。我怀疑这和退出有关。在一个单独的进程中运行,但我并没有足够的能力去弄清楚如何运行。是的。。。无法从其他进程更新UI。。。您必须通过队列/管道将数据传递给主线程/进程…事实证明,使用线程而不是多进程可以解决这个问题。如果你在编辑回答中提到这一点,我会接受。
from kivy.app import App
from random import choice
from time import sleep
from kivy.event import EventDispatcher
from kivy.uix.screenmanager import ScreenManager, Screen
from kivy.uix.button import Button
from kivy.properties import StringProperty
from multiprocessing import Process

class DrillScreen(Screen):
    answer = StringProperty('Initialized.')
    def __init__(self, **kwargs):
        self.thedrill = drill()
        self.thedrill.bind(on_answer = self.printtest)
        super(DrillScreen, self).__init__(**kwargs)
        self.answer = self.thedrill.answer

        b = Button(
                text = 'printtest()',
                size_hint = [ 0.1, 0.1 ],
                pos_hint = {'center_x':0.75,'center_y':0.5},
                )
        b.bind(on_release = self.printtest)
        print(self.ids)
        self.ids.wheelbox.add_widget(b)

    def printtest(self,*args):
        self.answer = self.thedrill.answer
        print('This is printtest(): ', self.ids.answerlabel.text)

    def startdrill(self):
        Process(target=self.thedrill.run).start()

class drill(EventDispatcher):
    def __init__(self):
        self.register_event_type('on_answer')
        self.answer = 'Default'

    def on_answer(self,*args):
        pass

    def run(self):

        while True:

            self.answer = str(choice(range(100)))
            self.dispatch('on_answer', self.answer)
            sleep(1)

class Manager(ScreenManager):
    pass

class TestingApp(App):
    def build(self):
        sm = Manager()
        s = DrillScreen(name='ds')
        sm.add_widget(s)
        sm.current = 'ds'
        return sm

TestingApp().run()
('This is printtest(): ', '8')
('This is printtest(): ', '60')
('This is printtest(): ', '6')
('This is printtest(): ', 'Default')
('This is printtest(): ', '66')
('This is printtest(): ', '68')
('This is printtest(): ', 'Default')
('This is printtest(): ', '89')
('This is printtest(): ', '69')
thedrill = ObjectProperty(None) # not really needed ... 

def __init__(self, **kwargs):
    self.thedrill = drill(kwargs['options'])
    self.thedrill.bind(on_answer = self.printtest)
    super(DrillScreen, self).__init__(**kwargs) # this will trigger the kv file section that exploded before ...