2017-06-06 40 views
0

私の.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') 

ラインはthedrillon_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') 

答えて

0

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を更新することを忘れないでください。...

+0

は楽しいし(時計または@mainthreadを使用して) ')' printtest(無attribute'の苦情がなくなっていない持っていますが、外観のラベルはまだ場合でも更新されません。 '文は正しい値を端末に出力します。私は 'answer = StringProperty( '')'と '' root.answer'というラベルを与え、 '' self.answer'を直接設定する '' printtest'の定義で作業を試みました。それはちょうど私が 'answer'を初期化し、決して変更しないものから始めます。また、 'def __init__'の前に' test 'と初期化し、 'super'の前に' self.answer = self.thedrill.answer'を設定すると正しく設定されます。同じ文が 'printtest'の中で失敗します。 – kuoytfouy

+0

これを調べるには小さな実行可能な例が必要かもしれません... –

+0

Galazner私は1つを含んでいました。私はこれが別のプロセスで走っている 'thedrill.run'と関係があると思っていますが、私はそれを理解するのに十分な能力がありません。 – kuoytfouy

関連する問題