My KivyアプリにコールバックにUrlRequest
が含まれているボタンがあります。私は、要求が完了している間、ユーザーに待つように要求するポップアップを提供したいと思います。問題は、リクエスト自体を実行するとポップアップが表示されないようにすることです。私は運のない別の場所にポップアップのopen()
メソッドを配置しようとしました。次の例では、ポップアップがUrlRequest
のon_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()
ブロックできます:
'wait()'は実際にスレッドをブロックします。しかし、同期リクエストライブラリから既存のコードを非同期UrlRequestに移行しています。私はその間に、物事を壊さないように 'wait() 'を使うことができると期待していました。私は[この既知の問題](https://groups.google.com/forum/#!topic/kivy-users/ERcZDjr3znE)のために単純には不可能かもしれないと思います。 – ScissorHill
@ScissorHill - あなたの古い行動を再現できるように私の答えを更新しました... –