Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to center text horizontally in a Kivy text input?

Tags:

python

kivy

I want to center a single line of text in Kivy text input. I'm going to use padding

widget.padding = [ (self.textinput.width - width of line) / 2, 20, 0, 0]

but i can't find the width of the line. How can I calculate or access the width of the line? enter image description here

like image 332
mnrl Avatar asked Jul 17 '16 13:07

mnrl


3 Answers

There is an internal TextInput._get_text_width method you can use to calculate proper padding:

from kivy.app import App
from kivy.uix.floatlayout import FloatLayout
from kivy.lang import Builder

Builder.load_string('''

<MyWidget>:
    TextInput:
        multiline: False
        on_text: root.update_padding(args[0])
        padding_x: self.width/2 # initial padding
''')

class MyWidget(FloatLayout):
    def update_padding(self, text_input, *args):
        text_width = text_input._get_text_width(
            text_input.text,
            text_input.tab_width,
            text_input._label_cached
        )
        text_input.padding_x = (text_input.width - text_width)/2

class MyApp(App):
    def build(self):        
        return MyWidget()

if __name__ == '__main__':
    MyApp().run()
like image 105
Nykakin Avatar answered Oct 18 '22 04:10

Nykakin


The solution above almost worked for me. Sometimes the padding wouldn't be updated correctly. Here is my slight change, setting text_width as a NumericProperty:

In Kivy:

<CenteredTextInput@TextInput>:
    multiline: False
    on_text: root.update_padding()
    padding_x: (self.width - self.text_width) / 2

In Python:

class CenteredTextInput(TextInput):
    '''
    A centered TextInput.
    '''

    text_width = NumericProperty()
    '''The text width
    '''

    def update_padding(self, *args):
        '''
        Update the padding so the text is centered
        '''
        self.text_width = self._get_text_width(
            self.text,
            self.tab_width,
            self._label_cached
        )
like image 42
yoel Avatar answered Oct 18 '22 04:10

yoel


You could make a textinput behind a button, and make the button visualize as the text input.

When pushing the button, put the focus to the textinput, and update the buttons text.

I have made an example here.

from kivy.uix.textinput import TextInput
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.floatlayout import FloatLayout
from kivy.uix.button import Button
from kivy.uix.label import Label
from kivy.clock import Clock
from kivy.app import App
from kivy import require

require('1.9.1')


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

        self.orientation = "vertical"

        self.cur = False

        self.textinput = TextInput(text='',halign="center",multiline=False)
        self.textinput.bind(text=self.on_text)

        self.button = Button(background_normal="",background_color=[0,0,0.1,1],font_size="40sp")
        self.button.bind(on_release=self.button_click)

        self.my_float_layout = FloatLayout()

        self.my_float_layout.add_widget(self.textinput)
        self.my_float_layout.add_widget(self.button)

        self.add_widget(Label(text="type text below",font_size="40sp"))
        self.add_widget(self.my_float_layout)

        Clock.schedule_interval(self.cursor, 0.5)


    def cursor(self,dt):          # function to visualize a cursor
        if self.textinput.focus:
            cur_pos = self.textinput.cursor[0]
            if not self.cur:
                self.button.text = self.textinput.text[:cur_pos] + "|" + self.textinput.text[cur_pos:]
                self.cur = True
            else:
                self.button.text = self.textinput.text[:cur_pos] + " " + self.textinput.text[cur_pos:]
                self.cur = False
        elif self.cur:
            self.button.text = self.textinput.text + " "
            self.cur = False



    def on_text(self, *args):     # function to set the button text
        self.button.text = self.textinput.text


    def button_click(self,*args): # function to focus the input
        self.textinput.focus = True



class MyApp(App):
    def build(self):
        return MyWidget()


if __name__ == "__main__":
    MyApp().run()
like image 2
el3ien Avatar answered Oct 18 '22 04:10

el3ien