我想创建一个只在用户将文本输入TextInput并单击确定按钮后才返回其值的函数。例如
n = PopupInput("What number should I add?")
print 5+n
我无法弄清楚如何编写一个暂停执行的kivy对话框并等到用户关闭它。在其他GUI工具包中,我会使用像
这样的东西while True:
if dialog.visable == False:
return int(textbox.text)
else:
wx.Yield()
允许我的代码只是坐在一个位置,同时允许GUI框架做它的事情。但是,我找不到Kivy的等效方法。
编辑:
这是我不成功的尝试(它凌乱)
def PopupOk(text, title='', btn_text='Continue'):
btnclose = Button(text=btn_text, size_hint_y=None, height='50sp')
content = BoxLayout(orientation='vertical')
p = Popup(title=title, content=content, size=('300dp', '300dp'),
size_hint=(None, None))
content.add_widget(Label(text=text))
ti = TextInput(height='50sp', font_size='50sp', input_type='number')
content.add_widget(ti)
def _on_d(*args):
p.is_visable = False
p.bind(on_dismiss=_on_d)
p.is_visable = True
content.add_widget(btnclose)
btnclose.bind(on_release=p.dismiss)
p.open()
while not p.is_visable:
EventLoop.idle()
return ti.text
答案 0 :(得分:3)
我会考虑另一种方式 - 你真正想要做的是在弹出窗口关闭时打印数字。
假设您有一个带有textinput的弹出窗口供用户写入,当弹出窗口关闭时,您可以popup.bind(on_dismiss=some_function)
运行some_function
。这意味着您需要做的就是编写一个弹出窗口的函数,检索文本框文本,并打印出您想要的任何答案。
我不确定这与你真正想做的事情有什么关系,但这是与Kivy的事件系统合作的一种更自然的方式。如果你有一些非常不同的要求,我可以回答不同。
编辑:看到你的编辑,这几乎就是你所做的,但我认为尝试以这种方式击败eventloop而不是顺其自然是一个坏主意。我会创建一个新函数(如上所述),它接受textinput并执行您真正想要的任何操作。通过将on_dismiss
绑定到此函数,只要用户绕过解除弹出窗口,就让kivy负责开始计算。
答案 1 :(得分:1)
Kivy实际上是围绕事件和异步回调的原则构建的。因为它使用OpenGL并且依赖于在GPU而不是CPU上渲染的帧,所以您永远不想使用阻塞代码。所以kivy使用事件绑定来规避问题。
这是一种方法。
from kivy.app import App
from kivy.uix.popup import Popup
from kivy.uix.button import Button
from kivy.uix.textinput import TextInput
class MainApp(App):
def build(self):
self.button = Button(text="Click",
on_release=self.get_caption)
return self.button
def get_caption(self, btn):
Popup(title="Enter text here",
content=TextInput(focus=True),
size_hint=(0.6, 0.6),
on_dismiss=self.set_caption).open()
def set_caption(self, popup):
self.button.text = popup.content.text
MainApp().run()
将内容放入弹出窗口时,给它一个“set_caption”函数,以便在它被解除时调用。你在那里回应这个变化。没有阻止。没等了。使用线程来阻止wxWidgets中的GUI阻塞,我真的认为这是一种更好的方法......; - )
干杯
答案 2 :(得分:1)
您可以使用以下代码实现所需的功能。您需要在主程序中将例程指定为方法:
import kivy
kivy.require('1.5.0') # replace with your current kivy version !
from kivy.uix.popup import Popup
from kivy.uix.button import Button
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.label import Label
from kivy.app import App
from kivy.clock import Clock
class YourApp(App):
def build(self):
return Button(text='Press for popup!', on_press=self.callpopup)
def callpopup(self, event):
dlg = MessageBox(titleheader="Titel Header", message="Any Message", options={"YES": "printyes()", "NO": "printno()"})
print "Messagebox shows as kivy popup and we wait for the \nuser action and callback to go to either routine"
def printyes(self):
# routine for going yes
print "You chose the Yes routine"
def printno(self):
# routine for going no
print "You chose the No routine"
class MessageBox(YourApp):
def __init__(self, titleheader="Title", message="Message", options={"OK": "self.ok()", "NO": "self.no()"}):
def popup_callback(instance):
"callback for button press"
# print('Popup returns:', instance.text)
self.retvalue = instance.text
self.popup.dismiss()
self.retvalue = None
self.options = options
box = BoxLayout(orientation='vertical')
box.add_widget(Label(text=message, font_size=20))
b_list = []
buttonbox = BoxLayout(orientation='horizontal')
for b in options:
b_list.append(Button(text=b, size_hint=(1,.35), font_size=20))
b_list[-1].bind(on_press=popup_callback)
buttonbox.add_widget(b_list[-1])
box.add_widget(buttonbox)
self.popup = Popup(title=titleheader, content=box, size_hint=(None, None), size=(400, 400))
self.popup.open()
self.popup.bind(on_dismiss=self.OnClose)
def OnClose(self, event):
self.popup.unbind(on_dismiss=self.OnClose)
self.popup.dismiss()
if self.retvalue != None:
command = "super(MessageBox, self)."+self.options[self.retvalue]
# print "command", command
exec command
if __name__ == '__main__':
YourApp().run()