1

I am trying to display numeric keyboard in bubble for TextInput in Kivy. Is it possible? So far I have:

Builder.load_string('''
<NumericKeyboard>
size_hint: (None, None)
size: (160, 120)
pos_hint: {'center_x': .5, 'y': .6}
BubbleButton:
    text: 'Cut'
BubbleButton:
    text: 'Copy'
BubbleButton:
    text: 'Paste'
''')

class NumericKeyboard(Bubble):
    pass

class CustomTextInput(TextInput):
def __init__(self, **kwargs):
    super(CustomTextInput, self).__init__(**kwargs)

def on_focus(self, instance, value):
    self.bubb = NumericKeyboard()
    self.add_widget(self.bubb)

But the bubble will not display.

qbranchmaster
  • 119
  • 1
  • 11

3 Answers3

2

Yes, it is possible to display numeric key pad using Kivy Bubble for TextInput widget. Please refer to the example below for details.

Note: The text input is not filtered.

Example

main.py

from kivy.app import App
from kivy.uix.floatlayout import FloatLayout
from kivy.uix.bubble import Bubble, BubbleButton
from kivy.uix.label import Label
from kivy.properties import ObjectProperty
from kivy.lang import Builder


class CustomBubbleButton(BubbleButton):
    pass


class NumericKeyboard(Bubble):
    layout = ObjectProperty(None)

    def __init__(self, **kwargs):
        super(NumericKeyboard, self).__init__(**kwargs)
        self.create_bubble_button()

    def create_bubble_button(self):
        numeric_keypad = ['7', '8', '9', '4', '5', '6', '1', '2', '3', '', '0', '.']
        for x in numeric_keypad:
            if len(x) == 0:
                self.layout.add_widget(Label(text=""))
            else:
                bubb_btn = CustomBubbleButton(text=str(x))
                self.layout.add_widget(bubb_btn)


class BubbleShowcase(FloatLayout):
    text_input = ObjectProperty(None)

    def show_bubble(self, *l):
        if not hasattr(self, 'bubb'):
            self.bubb = bubb = NumericKeyboard()
            self.bubb.arrow_pos = "bottom_mid"
            self.add_widget(bubb)


Builder.load_file("test.kv")


class TestBubbleApp(App):
    title = "Numeric Key Pad - Using Bubble"

    def build(self):
        return BubbleShowcase()


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

test.kv

#:kivy 1.10.0

<CustomBubbleButton>:
    on_release:
        app.root.text_input.text += self.text


<NumericKeyboard>:
    layout: layout

    size_hint: (None, None)
    size: (160, 120)
    pos_hint: {'center_x': .5, 'y': .6}

    GridLayout:
        id: layout
        cols: 3

<BubbleShowcase>:
    text_input: text_input

    canvas:
        Color:
            rgba: 0, 1, 1, 1
        Rectangle:
            size: self.width, self.height
    TextInput:
        id: text_input
        pos_hint: {'center_x': .5, 'y': .54}
        size_hint: (0.2, 0.06)
        cursor_blink: True
        font_size: 20
        multiline: False
        on_focus:
            root.show_bubble()

Output

Figure 1 - App Startup Figure 2 - Bubble Numeric Key Pad on_focus TextInput Figure 3 - Pressed Digit 3 Figure 4 - Pressed Decimal Point Figure 5 - Pressed Digits 1, 4, `, 5, and 9

ikolim
  • 15,721
  • 2
  • 19
  • 29
1

thank you @ikolim code and explain, I made some improvements and share with you。

  1. Replaced the picture background which kivy provide
  2. canvas and padding Specified,to make a rounded rectangle Appearance
  3. Remember: customer widgets add in Bubble Widget, Bubble Widget must add in FloatLayout
  4. code is running in win10-64,kivy2.0.0,py366(If there is a problem, please make a small modification)bubble_arrow_up.png Show resultsbubble_down.png delete.png

mycalculate.py

# !/usr/bin/env python  
# -*- coding: utf-8 -*- 
from functools import partial

from kivy.app import App
from kivy.core.window import Window
from kivy.core.text import LabelBase
from kivy.uix.bubble import Bubble, BubbleButton
from kivy.properties import ObjectProperty
from kivy.uix.boxlayout import BoxLayout


class NumBubbleButton(BubbleButton):
    pass


class Calculate(Bubble):
    content = ObjectProperty("")

    def __init__(self, **kwargs):
        super(Calculate, self).__init__(**kwargs)
        self.create_keyboard()

    def create_keyboard(self):
        num_key = ['7', '8', '9', '4', '5', '6', '1', '2', '3', ' ', '0', '⌫']
        for x in num_key:
            btn = NumBubbleButton(text=str(x))
            btn.bind(on_press=partial(self.add_text, str(x)))
            if x == " ":
                btn.disabled = True
                btn.background_disabled_normal = ""
            elif x == "⌫":
                btn.text = ""
                btn.background_normal = "delete.png"
            self.ids.calculator.add_widget(btn)
    @staticmethod
    def add_text(text, *args):
        print(text)

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

        self.cale = Calculate()
        self.cale.width, self.cale.height = 200, 400
        self.ids.float_grid.add_widget(self.cale)

class MyCalculateApp(App):
    def __init__(self, **kwargs):
        super(MyCalculateApp, self).__init__(**kwargs)

    def build(self):
        # Window.fullscreen = False
        # Window.left, Window.top, Window.size = 10, 0, (300, 500)
        return Cale()

if __name__ == "__main__":
    MyCalculateApp().run()

mycalculate.kv

<NumBubbleButton>:
    background_normal: ""
    background_color: 1, 1, 1, 1
    color: 0, 0, 0, 1
    bold: True
    font_size: "48px"
<Calculate>:
    size_hint: None, None
    orientation: "vertical"
    arrow_image: "bubble_arrow_up.png"
    background_image: "bubble_down.png"
    arrow_pos: "top_mid"


    BoxLayout:
        padding: 5, 5, 5, 0
        size_hint: 1, 1

        GridLayout:
            id: calculator
            canvas:
                Color:
                    rgba: 232/255, 232/255, 232/255, 1
                Rectangle:
                    pos: self.pos
                    size: self.size
            spacing: 2
            rows: 5
            cols: 3
    BoxLayout:
        size_hint: 1, 0.2
        padding: 5
        canvas.before:
            Color:
                rgba: 199/255, 31/255, 58/255, 1
            RoundedRectangle:
                pos: self.pos
                size: self.size
                radius: [0, 0, 10, 10]
        Button:
            background_normal: ""
            background_color: 199/255, 31/255, 58/255, 1
            font_size: "32px"
            text: t.t("Confirm")
            markup: True
            on_press: print("Confirm")
<Cale>:
    FloatLayout:
        id: float_grid
        GridLayout:
            id: grid_goods
27 Django
  • 11
  • 3
0

You cannot add a widget to a text input because it is not a layout. You should add your text input to a layout then add your bubble to this layout. Try this:

from kivy.app import App
from kivy.uix.bubble import Bubble
from kivy.uix.textinput import TextInput
from kivy.lang import Builder
from kivy.uix.floatlayout import FloatLayout

Builder.load_string('''
<NumericKeyboard>
    size_hint: (None, None)
    size: (160, 120)
    pos_hint: {'center_x': .5, 'y': .6}
    BubbleButton:
        text: 'Cut'
    BubbleButton:
        text: 'Copy'
    BubbleButton:
        text: 'Paste'
''')

class NumericKeyboard(Bubble):
    pass


class CustomTextInputLayout(FloatLayout):
    def __init__(self, **kwargs):
        super(CustomTextInputLayout, self).__init__(**kwargs)
        self.add_widget(CustomTextInput(self))


class CustomTextInput(TextInput):
    def __init__(self, layout,**kwargs):
        super(CustomTextInput, self).__init__(**kwargs)
        self.layout = layout

    def on_focus(self, instance, value):
        self.bubb = NumericKeyboard()
        self.layout.add_widget(self.bubb)

class MyTestApp(App):
    def build(self):
        return CustomTextInputLayout()

if __name__ == '__main__':
    MyTestApp().run()
Simon Mengong
  • 2,625
  • 10
  • 22