2017-06-20 17 views
0

動的に変化する値をポップアップ(ModalView)で表示します。メインウィジェットクラスのメソッドを使用してポップアップを開いたり閉じたりし、Kivy StringPropertyをポップアップのLabelにバインドします。問題があります - ポップアップが終了するたびに何かが残っています。 StringPropertyのすべてのオブザーバを表示すると、オブジェクトの数が累積される各サイクルのオープン/ディスマイズの方法が示されます。以下のサンプルコードを参照してください。 Raspbian Jessie(Pixel)の下で128MをVRAMに割り当てたRaspberry Pi 2でこれを実行すると、約1分でプログラムが正常に機能しなくなります。ポップアップが黒い画面を表示し始めます。私のコードで何か愚かなことをしていますか?ModalViewが終了した後にKivyプロパティオブザーバオブジェクトが残される

from kivy.app import App 
from kivy.lang import Builder 
from kivy.uix.boxlayout import BoxLayout 
from kivy.uix.button import Button 
from kivy.uix.label import Label 
from kivy.uix.modalview import ModalView 
from kivy.clock import Clock 
from kivy.properties import StringProperty 
from random import randint 


Builder.load_string(''' 
#:kivy 1.9.2 

<MainWidget>: 
    BoxLayout: 
     Button: 
''') 


class MainWidget(BoxLayout): 

    value_str = StringProperty() 

    def show_popup(self, even=True): 
     if even: 
      popup = ModalView(size_hint=(None, None), auto_dismiss=False, size=(700,480)) 
      popup_label = Label(font_size = 200, text_size=self.size, halign='center', valign='center') 
      self.bind(value_str=popup_label.setter('text')) # value_str must be a Kivy StringProperty 
      popup.add_widget(popup_label) 
      self.value_str = str(randint(0,100)) 
      popup.open() 
     else: # find all instances of ModalView and dismiss them 
      for widget in App.get_running_app().root_window.children: 
       if isinstance(widget, ModalView): 
        print "observers of value_str property:" 
        observers = self.get_property_observers('value_str') 
        for observer in observers: 
         print observer 

        widget.dismiss(force=True, animation=False)  

     Clock.schedule_once(lambda dt: self.show_popup(not even), 0.25) 



class MyApp(App): 
    def build(self): 
     mw=MainWidget() 
     Clock.schedule_once(lambda dt: mw.show_popup(),0) 
     return mw 


if __name__ == '__main__': 

    MyApp().run() 
+0

あなたは常にModalViewの新しいインスタンスを作成している:ここでは

コードです。オブジェクトの数は、RAMが満杯になるまで増加します。 – FJSevilla

+0

確かに私ですが、私がModalViewのインスタンスを作成するたびに、私もそれを却下します。これは、ガベージコレクションを得るために、それを完全に破壊するようではありません。私がKivyプロパティをModalViewインスタンスのLabel子のテキストフィールドにバインドしないと、問題は解決しません。 –

+0

私は、このような質問を再度述べると役に立つかもしれないと思います。静的コンテンツでModalViewの新しいインスタンスを連続して開いたり閉じたりすると、RAMがいっぱいになっても問題は発生しません。私は同じことをしますが、今回はModalViewインスタンスの子ウィジェット内のKivyプロパティ、VRAMにバインドしますか?いっぱいになるこれを防ぐ方法は? –

答えて

0

私は今ModalViewからそれを削除してModalView前MainWidgetにそれを追加することにより、ラベルの子を保存するこのHow to unbind a property automatically binded in Kivy language? に触発され、回避策を見つけましたが、次のポップアップのためにこれを逆転、その後、却下されます。このようにして、プロパティバインディングは1回だけ行われ、新しいオブザーバは作成されません。バインドされたプロパティに空の文字列を割り当てることで、ラベルを非表示にすることができます。

これはバグかもしれないと思います.ModalView dismiss()メソッドはオブザーバーの後ろに置いてはいけませんが、最新のKivyバージョン(1.10.1.dev0)ではテストできません。

from kivy.app import App 
from kivy.lang import Builder 
from kivy.uix.floatlayout import FloatLayout 
from kivy.uix.button import Button 
from kivy.uix.label import Label 
from kivy.uix.modalview import ModalView 
from kivy.clock import Clock 
from kivy.properties import StringProperty 
from random import randint 

Builder.load_string(''' 
#:kivy 1.9.2 

<MyLabel>: 
    font_size: 100 
    text_size: self.size 
    halign: 'center' 
    valign: 'center' 

<MainWidget>: 
    Button: 
     background_color: 0.5, 0.5, 1, 1 
''') 


class MyLabel(Label): 
    pass 

class MainWidget(FloatLayout): 

    value_str = StringProperty() 
    popup_label = MyLabel() 


    def __init__(self, **kwargs): 
     super(MainWidget, self).__init__(**kwargs) 
     self.bind(value_str=self.popup_label.setter('text')) # value_str must be a Kivy StringProperty 
     self.add_widget(self.popup_label) 



    def show_popup(self, even=True): 
     if even: 
      popup = ModalView(size_hint=(None, None), auto_dismiss=False, size=(500,380)) 
      self.remove_widget(self.popup_label) 
      popup.add_widget(self.popup_label) 
      self.value_str = str(randint(0,100)) 
      popup.open() 

     else: # find all instances of ModalView and dismiss them 
      for widget in App.get_running_app().root_window.children: 
       if isinstance(widget, ModalView): 
        print "observers of value_str property:" 
        observers = self.get_property_observers('value_str') 
        for observer in observers: 
         print observer 
        widget.remove_widget(self.popup_label) 
        self.add_widget(self.popup_label) 
        self.value_str ='' 
        widget.dismiss(force=True, animation=False) 
     Clock.schedule_once(lambda dt: self.show_popup(not even), 0.25) 


class MyApp(App): 
    def build(self): 
     mw=MainWidget() 
     Clock.schedule_once(lambda dt: mw.show_popup(),0) 
     return mw 


if __name__ == '__main__': 

    MyApp().run() 
関連する問題