Adam Gaskins
Adam Gaskins

Reputation: 399

Kivy button text alignment issue

I am trying to develop an email application in Kivy, basically just as an exercise to learn the in's and out's of the framework... I am trying to create the initial window and have reached a bit of a stumbling block! The idea is that it will simply display a list of emails in the inbox, much like any basic email app on a mobile device.

The problem I'm having is that I can't figure out how to get the text of each list item (which is a just a button) to align properly. Using "halign='left'" in my button will make the text align left, but only relative to each button; it's still centered within each button.

My actual app is a bit large to post, so this is a quick and dirty example I made from a stock Kivy example. (I realize this code isn't perfect... like I said quick and dirty for examples sake... it does work though!) So as you can see, the two rows of text on each button align with each other, but they don't all align overall. Can anyone suggest what I would do to make all the text align at, say, 10px from the left of each button? I did find one relative sounding item on StackOverflow, but it didn't really answer the question for example, it seemed to deal more with using images on buttons. I am new to Kivy, but I've read through the tutorials and documentation, as well as searched Google extensively - so any help would be greatly appreciated!

import kivy
kivy.require('1.0.8')

from kivy.app import App
from kivy.core.window import Window
from kivy.uix.button import Button
from kivy.uix.scrollview import ScrollView
from kivy.uix.gridlayout import GridLayout

import random


class ScrollViewApp(App):

    def build(self):
        # create a default grid layout with custom width/height
        layout = GridLayout(cols=1, spacing=10, size_hint=(None, None),
                            width=Window.width)

        # when we add children to the grid layout, its size doesn't change at
        # all. we need to ensure that the height will be the minimum required to
        # contain all the childs. (otherwise, we'll child outside the bounding
        # box of the childs)
        layout.bind(minimum_height=layout.setter('height'))

        # add button into that grid
        for i in range(30):
            btn = Button(text=str(i * random.random()) + '\n' + str(i * random.random()),
                         size=(300, 40),
                         size_hint=(None, None),
                         halign='left')
            layout.add_widget(btn)

        # create a scroll view, with a size < size of the grid
        root = ScrollView(size_hint=(None, None))
        root.size = (Window.width, Window.height)
        root.center = Window.center
        root.add_widget(layout)

        return root

if __name__ == '__main__':

    ScrollViewApp().run()

Upvotes: 15

Views: 22119

Answers (4)

qua-non
qua-non

Reputation: 4162

The documentation of Button starts with "A Button is a Label". Even for Widgets that don't mention their lineage explicitly, you should take a note of the second line in the API doc of the Widget in question. In this case "Bases: kivy.uix.label.Label".

This establishes that the button inherits from a Label. (I am explicitly mentioning this because this part of looking at the base Class's inherited properties sometimes is not intuitive for everyone).

If you look at the Docs for label, specifically the halign property, it asks you to utilize text_size to achieve proper text alignment. What this means is the text is aligned inside a bounding box that is set by the text_size property. This property can be set to be:

a) The size of the Widget. text_size: self.size

b) Less than the size of the size of the widget (what you are looking for) text_size: self.width - dp(10), self.height - dp(10)

c) Unconstrained on one of the sides text_size: self.width, None

d) or both text_size: None, None

e) or constrained to a different Widget text_size: other_button.size

The reason for using text_size is to give more control to the user. You should also look at the textalign example

Upvotes: 31

Avi ba
Avi ba

Reputation: 461

As explained by qua-non ,a Button is a Label therefore you can look at the Label proprieties in how to achieve that. Because I didn’t see much on this, I want to add a small piece of code that can help other programmers.
I’ll show how you can make button with label and adjust the text inside.

#disable multi-touch emulation
from kivy.config import Config
Config.set('input', 'mouse', 'mouse,multitouch_on_demand')
from kivy.app import App
from kivy.lang import Builder
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.button import Button
from kivy.uix.image import Image   
#--------------------------------------------------------------------
Builder.load_string("""
<RootWidget>:
  BoxLayout:
    orientation: 'vertical'
    padding: "10dp"

    BoxLayout:
      size_hint_y: 3
      Widget: # to fill the line from left

      Button:
        text: "Button"
        font_size: 40
        text_size: self.size     
        halign: 'center'
        valign: 'bottom'
        padding_y: 10

        #Adding Image you can comment this part    
        Image:
          source: 'img/calender1.png'
          center_x: self.parent.center_x
          center_y: self.parent.center_y +10

      Widget:# to fill the line from right

    BoxLayout:
      size_hint_y: 10    

""")
#-----------------------------------------------------------------------
class RootWidget(BoxLayout):
  pass

#-----------------------------------------------------------------------    
class MyApp(App):
    def build(self):
      return RootWidget()


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

The main part goes in the Button. you can play with font, alignment and padding to get any desired result.

Button:
    text: "Button"
    font_size: 40
    text_size: self.size     
    halign: 'center'
    valign: 'bottom'
    padding_y: 10

Upvotes: 4

Abhipso Ghosh
Abhipso Ghosh

Reputation: 555

If you want to avoid numbers in text.size, then try this:

text_size: self.size

Upvotes: 3

HYRY
HYRY

Reputation: 97261

You need to set text_size property, something like:

btn.text_size = (290, 40)

Upvotes: 7

Related Questions