私の.pyファイルと.kvファイルから、以下の関連セクションがあります。.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()
<DrillScreen>:
FloatLayout:
FloatLayout:
size_hint: 1.0, None
height: self.width
pos_hint: {'center_x':0.5,'center_y':0.5}
id: wheelbox
background_color: 1,1,1,1
pos: 0, 200
Label:
id: answerlabel
pos_hint: {'center_x':0.5, 'center_y':0.5}
text: root.thedrill.answer
Button:
text: 'Start'
size_hint: 0.5, 0.1
on_release: root.startdrill()
Button:
text: 'Back'
size_hint: 0.5, 0.1
pos_hint: {'x':0.5}
これは私にエラーAttributeError: 'DrillScreen' object has no attribute 'thedrill'
を与えます。ラベルテキスト内のroot.thedrill.answer
をリテラル文字列に変更すると、正常に実行され、printtest()
の出力から、内部的に変更されますが、その表示は更新されません。 .kvファイルからクラス属性にアクセスするか、ラベル表示を.pyファイルから設定したいと思います。ありがとうございました。
EDIT:ヨアフGlaznerのアドバイスに応じ 進むと、私も何が起こっているのか確認するためにprinttest()
機能に結合するボタンを追加しようとした、と私は別のバインディングからの呼び出しが異なる出力を生成することを確認するために困惑しています。ここでの.pyから変更クラスがあります:
class DrillScreen(Screen):
answer = StringProperty('alo')
def __init__(self, **kwargs):
self.thedrill = drill(kwargs['options'])
self.thedrill.bind(on_answer = self.printtest)
super(DrillScreen, self).__init__(**kwargs)
self.answer = self.thedrill.answer
b = Button(text = 'Test',
size_hint = [0.1,0.1],
pos_hint = {'top':1,'right':1})
b.bind(on_release = self.printtest)
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()
.kvファイルへの唯一の変更は、ラベルテキストがroot.answer
を指していることです。これを実行して(startdrill()
を呼び出す.kvのボタンをクリックすると)、は一定の間隔で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')
ラインはthedrill
のon_answer
派遣の結果であり、「デフォルト」を持つものは、ボタンのクリックからです。私はその違いに何が影響するか想像できません。 drill
クラスを調べると、すぐ前の値に戻す必要はありません(実際には.answer
を設定してイベントを送出する行の次の行にはsleep(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()
との.py:
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()
[スタート]ボタンをクリックすると、端末秒ごとに乱数を吐き、独自のプロセスでthedrill.run開始し、しばらくprinttest()ボタンをクリックすると、ラベルのテキスト値として「Default」が出力されます。出力例:あなたはあなたの__init__機能の順序を変更する必要が
('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')
は楽しいし(時計または@mainthreadを使用して) ')' printtest(無attribute'の苦情がなくなっていない持っていますが、外観のラベルはまだ場合でも更新されません。 '文は正しい値を端末に出力します。私は 'answer = StringProperty( '')'と '' root.answer'というラベルを与え、 '' self.answer'を直接設定する '' printtest'の定義で作業を試みました。それはちょうど私が 'answer'を初期化し、決して変更しないものから始めます。また、 'def __init__'の前に' test 'と初期化し、 'super'の前に' self.answer = self.thedrill.answer'を設定すると正しく設定されます。同じ文が 'printtest'の中で失敗します。 – kuoytfouy
これを調べるには小さな実行可能な例が必要かもしれません... –
Galazner私は1つを含んでいました。私はこれが別のプロセスで走っている 'thedrill.run'と関係があると思っていますが、私はそれを理解するのに十分な能力がありません。 – kuoytfouy