47231


kivyで簡単なプログラムを試しに作っていたんですが  
題にあるよう、インスタンス?をまたいでの変数代入を行うとエラーがおきます

[code]

    TypeError: 'kivy.properties.DictProperty' object has no attribute '__getitem__'
    
[/code]

[code]

    class pullscreen(Screen):
        def clicked(self):
            x = np.random.randint(1,10,1)
            if x == 5:
                result.ids["res"].text = "1"
            elif x % 2 == 0:
                result.ids["res"].text = "2"
            else:
                result.ids["res"].text = "3"
            sm.current = "ans"
    
    class result(Screen):
        def back(self):
            sm.current = "pull"
    
[/code]

self.idsとするとそのインスタンス内の変数を指定するため望む結果が得られません。  
どうすれば良いのでしょうか？よろしくお願いします

pyファイル

[code]

    from kivy.config import Config
    Config.set("graphics", "resizable", False)
    Config.set("graphics", "width", 640)
    Config.set("graphics", "height", 480)
    
    from kivy.app import App
    from kivy.uix.screenmanager import ScreenManager, Screen
    
    import numpy as np
    
    sm = ScreenManager()
    
    class pullscreen(Screen):
        def clicked(self):
            x = np.random.randint(1,10,1)
            if x == 5:
                result.ids["res"].text = "1"
            elif x % 2 == 0:
                result.ids["res"].text = "2"
            else:
                result.ids["res"].text = "3"
            sm.current = "ans"
    
    class result(Screen):
        def back(self):
            sm.current = "pull"
    
    
    class Amidakuji(App):
        def build(self):
            sm.add_widget(pullscreen(name = "pull"))
            sm.add_widget(result(name = "ans"))
            return sm
    
    
    if __name__ == '__main__':
        Amidakuji().run()
    
[/code]

kvファイル

[code]

    <PaddingBoxLayout@BoxLayout>:
        padding: 20
    
    <pullscreen>:
        BoxLayout:
            orientation: "vertical"
            canvas.before:
                Color:
                    rgba: 0.9,0.9,0.9,1
                Rectangle:
                    pos: self.pos
                    size: self.size
            Label:
                text: "Amidakuji"
                color: 0,0,0,1
                size_hint_y: 0.2
                font_size: 32
    
            BoxLayout:
                orientation: "horizontal"
                Button:
                    text: "uranau"
                    on_press: root.clicked()
    
    <result>:
        BoxLayout:
            orientation: "vertical"
            canvas.before:
                Color:
                    rgba: 0.9,0.9,0.9,1
                Rectangle:
                    pos: self.pos
                    size: self.size
            Label:
                text: "result"
                color: 0,0,0,1
                size_hint_y: 0.2
                font_size: 32
    
            BoxLayout:
                orientation: "horizontal"
    
                Label:
                    id: res
    
                Button:
                    text: "mo-ikkai, uranau"
                    on_press: root.back()
    
[/code]


CC BY-SA 4.0
2018-07-31T07:06:38.907
47123
2018-08-04T09:42:08.323
2018-07-31T13:34:35.553
19110
question
python python2 kivy
kivyでインスタンス?をまたいで変数代入ができない


resultは

[code]

    class result(Screen):
    
[/code]

とあるのでクラスであってインスタンスではありません。  
kivyは分かりませんけど、

[code]

            sm.add_widget(result(name = "ans"))
    
[/code]

とありますから、「result(name =
"ans")」の戻り値（おそらくresultのインスタンス）を参照すべきであって、resultクラスそのものを参照したために発生したエラーなのでしょう。

解決策としてインスタンスをグローバルに参照できるようにする手もありますが、  
ScreenManagerのメソッドにget_screen(name)というメソッドがあるようなので、

[code]

        def clicked(self):
            x = np.random.randint(1,10,1)
            ans = sm.get_screen("ans")
            if x == 5:
                ans.ids["res"].text = "1"
                  :
    
[/code]

とでもしてみるとどうでしょうか？

* * *

追記  
グローバル化とはAmidakuji#buildで生成したインスタンスをpullscreen#clickedで参照したいので、smと同じく、どちらからでも参照できるようにしておくための方法です。  
具体的には下記の様になると思います。

[code]

        :
    import numpy as np
    
    sm = ScreenManager()
    result_ans = result(name = "ans")
    
    class pullscreen(Screen):
        :
    
        :
    class Amidakuji(App):
        def build(self):
            sm.add_widget(pullscreen(name = "pull"))
            sm.add_widget(result_ans)
            return sm
        :
    
[/code]

このようにして、あらかじめインスタンスを作っておきます。  
この場合clickedではresult_ansを使います。  
ただ、kivyの作法を知らないので、もしかしたらAmidakuji#build内でインスタンスを作るべきかもしれません。  
その場合はこんな感じになるかもしれません。

[code]

        :
    import numpy as np
    
    sm = ScreenManager()
    result_ans = None
    
    class pullscreen(Screen):
        :
    
        :
    class Amidakuji(App):
        def build(self):
            global result_ans
            sm.add_widget(pullscreen(name = "pull"))
            result_ans = result(name = "ans")
            sm.add_widget(result_ans)
            return sm
        :
    
[/code]

こちらでは、result_ansを通してメソッドで作ったインスタンスにアクセスします。  
もちろんclickedでもresult_ansを使います。

sm.get_screen("ans")は単純にsm.add_widget()で登録したもののうち、name="ans"のもの、つまりresult(name
= "ans")を得るメソッドです。  
ここにids以下の中身があるわけなので。

いずれも登録する／したresult(name = "ans")をどうやって手に入れるかという話です。  
今回の場合、ScreenManagerに、実際に登録されているScreenインスタンスを得る手段であるget_screenが用意されているわけなので、それを使うのが一番素直な方法だと思います。


CC BY-SA 4.0
2018-08-04T02:20:52.233
47231
2018-08-04T09:42:08.323
2018-08-04T09:42:08.323
12301
12301
47123
answer