Python Kivy 在 Popup 内的按钮之间切换

Posted

技术标签:

【中文标题】Python Kivy 在 Popup 内的按钮之间切换【英文标题】:Python Kivy switching between button inside Popup 【发布时间】:2020-08-05 22:46:35 【问题描述】:

我想在这里为 python kivy 桌面应用程序寻求帮助,我有一个小问题,但它很烦人。我遇到的问题是在带有键盘“Tab 键”的 kivy 弹出窗口中的两个按钮(是按钮和否按钮)之间切换不起作用,而且我希望能够按下“Enter 键”来处理所选按钮的功能。

这是我的弹出窗口的样子:

Popup screenshot

弹窗代码如下:

from kivy.app import App
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.button import Button
from kivy.uix.popup import Popup
from kivy.uix.label import Label


class testWindow(BoxLayout):
    def __init__(self, **kwargs):
        super().__init__(**kwargs)

        def yes_btn(instance):
            print("this function is called.")

        contents = BoxLayout(orientation='vertical')
        content_text = Label(text="Lanjutkan Transaksi?")
        pop_btn = BoxLayout(spacing=10)
        btn_yes = Button(text='Ya', size_hint_y=None, height=40)
        btn_no = Button(text='Tidak', size_hint_y=None, height=40)
        pop_btn.add_widget(btn_yes)
        pop_btn.add_widget(btn_no)
        contents.add_widget(content_text)
        contents.add_widget(pop_btn)

        pop_insert = Popup(title="Confirmation Message", content=contents, size_hint=(None, None), size=(300, 300))

        btn_yes.bind(on_release=yes_btn)
        btn_no.bind(on_release=pop_insert.dismiss)

        pop_insert.open()


class testApp(App):
    def build(self):
        return testWindow()


if __name__ == '__main__':
    m = testApp()
    m.run()

当我使用鼠标单击按钮时,弹出窗口正常运行。如上面的弹出图片,我想让 Yes Button 聚焦,当我按下“Enter 键”弹出窗口关闭并运行我想要的功能。同时在按钮之间切换只需按“Tab键”。

我一直在寻找解决问题的方法,但仍然没有结果,所以请知道如何解决我的问题的人帮助我。

【问题讨论】:

【参考方案1】:

这是对您的代码的修改,我认为它可以满足您的需求:

from kivy.app import App
from kivy.core.window import Window
from kivy.lang import Builder
from kivy.properties import BooleanProperty
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.button import Button
from kivy.uix.popup import Popup
from kivy.uix.label import Label
from kivy.uix.behaviors import FocusBehavior

# This is a Button that also has focus behavior
class FocusButton(FocusBehavior, Button):
    first_focus = BooleanProperty(False)

    def on_parent(self, widget, parent):
        # if first_focus is set, this Button takes the focus first
        if self.first_focus:
            self.focus = True


class MyPopup(Popup):
    def keydown(self, window, scancode, what, text, modifiers):
        if scancode == 13:
            for w in self.walk():
                if isinstance(w, FocusButton) and w.focus:
                    w.dispatch('on_press')

    def keyup(self, key, scancode, codepoint):
        if scancode == 13:
            for w in self.walk():
                if isinstance(w, FocusButton) and w.focus:
                    w.dispatch('on_release')

    def on_dismiss(self):
        Window.unbind(on_key_down=self.keydown)
        Window.unbind(on_key_up=self.keyup)

Builder.load_string('''
# provide for a small border that indicates Focus
<FocusButton>:
    canvas.before:
        Color:
            rgba: 1,1,1,1
        Rectangle:
            pos: self.x-2, self.y-2
            size: (self.size[0]+4, self.size[1]+4) if self.focus else (0,0)
''')


class testWindow(BoxLayout):
    def __init__(self, **kwargs):
        super().__init__(**kwargs)

        def yes_btn(instance):
            print("this function is called.")

        contents = BoxLayout(orientation='vertical')
        content_text = Label(text="Lanjutkan Transaksi?")
        pop_btn = BoxLayout(spacing=10)

        # set first_focus to True for this Button
        self.btn_yes = FocusButton(text='Ya', size_hint_y=None, height=40, first_focus=True)
        self.btn_no = FocusButton(text='Tidak', size_hint_y=None, height=40)
        pop_btn.add_widget(self.btn_yes)
        pop_btn.add_widget(self.btn_no)
        contents.add_widget(content_text)
        contents.add_widget(pop_btn)

        pop_insert = MyPopup(title="Confirmation Message", content=contents, size_hint=(None, None), size=(300, 300))

        self.btn_yes.bind(on_release=yes_btn)
        self.btn_no.bind(on_release=pop_insert.dismiss)

        # bind to get key down and up events
        Window.bind(on_key_down=pop_insert.keydown)
        Window.bind(on_key_up=pop_insert.keyup)

        pop_insert.open()

class testApp(App):
    def build(self):
        return testWindow()


if __name__ == '__main__':
    m = testApp()
    m.run()

此代码将FocusBehavior 添加到Button 以创建FocusButton,并将按键按下和按键向上处理添加到MyPopup 类。

【讨论】:

亲爱的约翰,非常感谢你,它工作得很好。我实际上已经尝试创建 CustomButton(FocusBehavior, Button) 但仍然无法正常工作,因为该类下面的方法非常不同,我确信这就是为什么我的方法根本不起作用。

以上是关于Python Kivy 在 Popup 内的按钮之间切换的主要内容,如果未能解决你的问题,请参考以下文章

Kivy popup Filechooser传递变量(选择)

Kivy Popup 无法访问 root 方法

在未调用 Popup.open() 的方法中触发 Popup.dismiss() (kivy)

如何在 Kivy 中使用 Popup 运行复选框小部件?

在 Kivy 中,为啥 popup.dismiss() 不从内存中删除弹出窗口?

Kivy:为啥弹窗是半透明的?