使用Kivy创建输入对话框

时间:2014-02-19 22:41:39

标签: android python kivy

我想创建一个只在用户将文本输入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

3 个答案:

答案 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()