2017-01-21 7 views
2

My KivyアプリにコールバックにUrlRequestが含まれているボタンがあります。私は、要求が完了している間、ユーザーに待つように要求するポップアップを提供したいと思います。問題は、リクエスト自体を実行するとポップアップが表示されないようにすることです。私は運のない別の場所にポップアップのopen()メソッドを配置しようとしました。次の例では、ポップアップがUrlRequeston_progress()コールバックで開かれている:Kivy:メインスレッドによってポップアップがブロックされます

from kivy.uix.dropdown import DropDown 
from kivy.uix.button import Button 
from kivy.app import App 
from kivy.uix.screenmanager import ScreenManager, Screen 
from kivy.lang import Builder 
from kivy.garden.navigationdrawer import NavigationDrawer 
from kivy.network.urlrequest import UrlRequest 
from kivy.uix.popup import Popup 
from kivy.uix.label import Label 
import urllib 

kv = ''' 
<[email protected]>: 
    canvas: 
     Color: 
      rgb: (0.09,0.65,0.8) 
     Rectangle: 
      pos: self.pos 
      size: self.size 

    Button: 
     size_hint: .3, .2 
     pos_hint: {'center_x': .5,'center_y': .25} 
     text: 'Call Request' 
#   on_press: app.p.open() 
     on_release: app.callback1() 
    Label: 
     text: 'This is ' + root.name 
     font_size: '50sp' 

<MyNavDrawer>: 
    BoxLayout: 
     orientation: 'vertical' 
     size_hint_y: .25 
     pos_hint: {'center_y':.5} 
     Button: 
      text: 'Screen 1' 
      on_press: app.callback2('screen1') 
     Button: 
      text: 'Screen 2' 
      on_press: app.callback2('screen2')  
    SMRoot: 

<SMRoot>: 
    ScreenTemplate: 
     name: 'screen1'    

    ScreenTemplate: 
     name: 'screen2'  
''' 

Builder.load_string(kv) 
class SMRoot(ScreenManager): 
    pass 

class SignUpScreen(Screen): 
    pass 

class myNavDrawer(NavigationDrawer): 
    pass 

class myApp(App): 

    popup_opened = False 
    p=Popup(title="Posting request...", 
      content=Label(text="... Please wait"), 
      size=(100, 100), 
      size_hint=(0.5, 0.5), 
      auto_dismiss = False) 
    def build(self): 
     self.mynavdrawer = myNavDrawer() 
     return self.mynavdrawer 

    def on_success(self, req, results): 
     print 'In on_success: '+ results 
     self.p.title = 'Success' 
     self.p.content = Label(text=results) 
     self.p.auto_dismiss = True 
     popup_opened = False 


    def on_failure(self, req, results): 
     self.p.title = 'Failure' 
     self.p.content = Label(text=results) 
     print 'In on_failure: '+ results 
     self.p.auto_dismiss = True 

    def on_error(self, req, results): 
     self.p.title = 'Error' 
     self.p.content = Label(text=results.strerror) 
     print 'In on_error: '+ results.strerror 
     self.p.auto_dismiss = True  

    def on_progress (self, req, results, chunk): 
     if not self.popup_opened: 
      print 'In on_progress: '+ str(results) 
      self.p.open() 
      self.popup_opened = True 


    def callback1(self): 
     params={'show_env':'1'} 
     params = urllib.urlencode(params) 
     headers = {'Content-type': 'application/x-www-form-urlencoded', 
        'Accept': 'text/plain'} 
     url = 'https://httpbin.org/get' 
     req = UrlRequest(url, 
         self.on_success, 
         req_body = params, 
         req_headers = headers, 
         on_failure=self.on_failure, 
         on_error=self.on_error, 
         on_progress=self.on_progress, 
         timeout=4) 
     req.wait() 
     print 'After UrlRequest' 


if __name__ == '__main__': 
    myApp().run() 

はこれを実行する要求が目的に反している、完成された後にポップアップが表示されるようになります。

<[email protected]>の下にあるボタンのコメント付きon_press: app.p.open()バインディングに注目してください。理想とはかけ離れた回避策であることを除けば、これは完全に機能します。 UrlRequestが送信されると、いつでもポップアップを開くことができます。上記の回避策はすべてのボタンに適用する必要があります。

コールバックが実行されている間にメインスレッドからボタンを開く方法に関するアイデアは高く評価されます。私はClock.schedule_once()も使ってみました。 docsから、EventDispatcher.dispatch()がそのトリックを行うかもしれないようですが、私はどのイベントをディスパッチするのか分かりません。メインスレッド上

req.wait() 

ブロックできます:

答えて

0

私はこの行を考えます。 削除します。私は「:免責事項

@delayable 
def callback1(self): 
    ... 
    while not reg.is_finished: 
     yield 0.02 # sleep for 20 ms... 

    ... #req is ready now... 

kivyoavから)言われて、あなたは 遅延可能を使用して、この動作を再現できることを代わりに req.wait()

の - あなたも早くポップアップを開くことができます私の著者kivyoav

+0

'wait()'は実際にスレッドをブロックします。しかし、同期リクエストライブラリから既存のコードを非同期UrlRequestに移行しています。私はその間に、物事を壊さないように 'wait() 'を使うことができると期待していました。私は[この既知の問題](https://groups.google.com/forum/#!topic/kivy-users/ERcZDjr3znE)のために単純には不可能かもしれないと思います。 – ScissorHill

+0

@ScissorHill - あなたの古い行動を再現できるように私の答えを更新しました... –

0

私はあなたと同じ問題を抱えていました。 UrlRequestがメインスレッドで実行されます。これは、メインスレッドが実行されない限り、UIが更新されないことを意味します。これは、callback1関数内でブロックされているためです。 あなたのやりたいことは、UrlRequestの新しいスレッドを作成することです。

関連する問題