I am programming a Chat Bot and I want to build a GUI using kivy. To make the chat I am using labels in a scrollview:
GridLayout:
cols: 1
rows: 0
ScrollView:
size: self.size
do_scroll_x: False
Label:
id: msg
text_size: self.width,None
size_hint_y: None
height: self.texture_size[1]
font_size: 20
Python Code:
def send(self,x):
#global msgback
self.msg_list.text += str(x + "\n")
The problem is, that I do not know how to make the valign, that only makes the messages from the user on the right side. How do I do that?
Use halign to align text to the right.
Label:
id: msg
text_size: self.width,None
size_hint_y: None
height: self.texture_size[1]
font_size: 20
halign: 'right'
valign: 'middle'
Label » halign
halign
Horizontal alignment of the text.
halign is an OptionProperty and defaults to ‘left’. Available options
are : left, center, right and justify.
Warning
This doesn’t change the position of the text texture of the Label
(centered), only the position of the text in this texture. You
probably want to bind the size of the Label to the texture_size or set
a text_size.
Related
So I want to make label with scrollable text that isn't the size of the whole app?
I know that to make scrollable text i have to size_hint_y: None.But I want to make it visible only in bottom size_hint_y: 0.3
Here is part of code with that label.
FloatLayout:
ScrollView:
Label:
text: root.timesLabel
font_size: 20
text_size: (self.width, None)
pos_hint: {"x": 0, "y": 0}
size_hint_y: None
height: self.texture_size[1]
I'm looking for how I can change the font size of all text in a kivy FileChooserListView class. I am hoping to do so in pure python if possible. I like that the standard Label and Button uix classes take font_size as an initialize parameter, but it appears the FileChooserListView does not. If doing so in pure python isn't an easy approach and there's a good .kv file approach, I'd take that too. Thanks!
There is no direct way to do that, but you can fiddle with the FileListEntry template that the FileChooserListView uses to display the entries. In that template, you can adjust the font sizes used. Here is my attempt at that:
Builder.load_string('''
[FileListEntry#FloatLayout+TreeViewNode]:
locked: False
entries: []
path: ctx.path
# FIXME: is_selected is actually a read_only treeview property. In this
# case, however, we're doing this because treeview only has single-selection
# hardcoded in it. The fix to this would be to update treeview to allow
# multiple selection.
is_selected: self.path in ctx.controller().selection
orientation: 'horizontal'
size_hint_y: None
height: '96dp' if dp(1) > 1 else '48dp' # height must be big enough to hold font sized below
# Don't allow expansion of the ../ node
is_leaf: not ctx.isdir or ctx.name.endswith('..' + ctx.sep) or self.locked
on_touch_down: self.collide_point(*args[1].pos) and ctx.controller().entry_touched(self, args[1])
on_touch_up: self.collide_point(*args[1].pos) and ctx.controller().entry_released(self, args[1])
BoxLayout:
pos: root.pos
size_hint_x: None
width: root.width - dp(10)
Label:
id: filename
font_size: '48dp' # adjust this font size
size_hint_x: None
width: root.width - sz.width # this allows filename Label to fill width less size Label
text_size: self.width, None
halign: 'left'
shorten: True
text: ctx.name
Label:
id: sz
font_size: '48dp' # adjust this font size
#text_size: self.width, None
size_hint_x: None
width: self.texture_size[0] # this makes the size Label to minimum width
text: '{}'.format(ctx.get_nice_size())
''')
This is based heavily on the FileListEntry template in style.kv. There are two font_sizes that you can adjust, and a height for the entry. All three must be coordinated to get a reasonable result.
I have this kivy file here:
<Help>:
Label:
text: "[b]Help Page[/b]\n"
font_size: 30
markup: True
valign: "top"
color: 0,0,0,1
Label:
text: "[b] How To Use:[/b]\n"
font_size: 30
markup: True
valign: 'top'
color: 0,0,0,1
However, the text does not go to the top of the page. This is the output:
What is wrong with this? and may I also ask about how to format those overlapping text. Thanks :)
edit:
This is what I want to happen with the text:
desired output
So to get that result I tried using the valign and halign to format the text but it does not seem to work. Hope this clarified my question :)
Display Text at Top
To display the text at top using valign: 'top', replace text_size: root.width, None with text_size: root.width, root.height
Snippet
<Help>:
Label:
id: help
text_size: root.width, root.height
markup: True
valign: 'top'
halign: 'center'
color: 0,0,0,1
Output
Display Both Strings as One
To display both strings, "How to Operate: Some text here" and "Some title Some more text" as one, we will do the following:
kv file
<Help>:
Label:
id: help
text_size: root.width, None
markup: True
halign: 'center'
color: 0,0,0,1
Python Code
class Help(Screen):
def on_pre_enter(self, *args):
self.ids.help.text = "[size=30][b]How to Operate[/b][/size]\nSome text here" + \
"\n\n[size=30][b]Some title[/b][/size]\nSome more text"
Output - Combined Text
Text Overlapping
The Label's text are overlapping because you are adding two Label widgets on-top each other in a Screen Layout.
Add a BoxLayout as parent of the two Label widgets to prevent text overlapping.
Text Wrapping
Wraps the text at a certain width, provide the width. For example, a Label to be created in a box with width=200 and unlimited height.
Label(text='Very big big line', text_size=(200, None))
Snippet
<Help>:
BoxLayout:
orientation: 'vertical'
Label:
text_size: dp(230), None
height: self.texture_size[1]
text: "[size=30][b]How to Operate[/b][/size]Some text here"
markup: True
valign: "top"
halign: 'center'
color: 0,0,0,1
Label:
text_size: dp(150), None
text: "[size=30][b]Some title[/b][/size]Some more text"
markup: True
valign: 'top'
halign: 'center'
color: 0,0,0,1
Output
Text Alignment
Add text_size: self.size
Snippet
<Help>:
Label:
text_size: self.size
text: "[b]Help Page[/b]\n"
font_size: 30
markup: True
valign: "top"
color: 0,0,0,1
Label:
text_size: self.size
text: "[b] How To Use:[/b]\n"
font_size: 30
markup: True
valign: 'top'
color: 0,0,0,1
Text alignment and wrapping
In order for the halign and valign alignment properties to
take effect, set the text_size, which specifies the size of the
bounding box within which text is aligned.
Output
I'm new to Kivy and still working out the best way to use it. Currently, I'm taking an example from their repo (textsize demo) and attempting to use layout concepts in a personal project.
At the end of the day, all I want is a "navbar" at the top of my screen and a content section below it. At the moment, I'm trying to accomplish this with a BoxLayout which includes a StackLayout (nav items) and a GridLayout (other content).
My Code Snippet:
<WindowWidget>:
BoxLayout:
orientation: 'vertical'
StackLayout:
Label:
text: 'Test1'
Label:
text: 'Test1.1'
Label:
text: 'Test2'
This code produces this: Kivy Screenshot.
I don't understand why label 1.1 is pushed down on top of label 2 rather than appearing beside label 1.
I added the following code taken from the kivy examples hoping the height setting would add some clarity, but I get the error below:
Code:
<StackLayout>:
size_hint_y: None
spacing: dp(6)
padding: dp(6), dp(4)
height: self.minimum_height
Error:
Warning, too much iteration done before the next frame. Check your
code, or increase the Clock.max_iteration attribute
This is caused by my inclusion of the "height: self.minimum_height" line. However, this works in the demo, so I'm not sure how I managed to screw it up. I'll include the example's kv code below for reference.
The original:
BoxLayout:
orientation: 'vertical'
HeadingLabel:
text: 'These modify all demonstration Labels'
StackLayout:
# Button is a subclass of Label and can be sized to text in the same way
Button:
text: 'Reset'
on_press: app.reset_words()
ToggleButton:
text: 'Shorten'
on_state:
app.shorten=self.state=='down'
ToggleButton:
text: 'max_lines=3'
on_state:
app.max_lines=3 if self.state=='down' else 0
Spinner:
text: 'bottom'
values: 'bottom', 'middle', 'top'
on_text: app.valign=self.text
Spinner:
text: 'left'
values: 'left', 'center', 'right', 'justify'
on_text: app.halign=self.text
GridLayout:
id: grid_layout
cols: 2
height: cm(6)
size_hint_y: None
HeadingLabel:
text: "Default, no text_size set"
HeadingLabel:
text: 'text_size bound to size'
DemoLabel:
id: left_content
disabled_color: 0, 0, 0, 0
DemoLabel:
id: right_content
text_size: self.size
padding: dp(6), dp(6)
ToggleButton:
text: 'Disable left'
on_state:
left_content.disabled=self.state=='down'
# Need one Widget without size_hint_y: None, so that BoxLayout fills
# available space.
HeadingLabel:
text: 'text_size width set, size bound to texture_size'
text_size: self.size
size_hint_y: 1
DemoLabel:
id: bottom_content
# This Label wraps and expands its height to fit the text because
# only text_size width is set and the Label size binds to texture_size.
text_size: self.width, None
size: self.texture_size
padding: mm(4), mm(4)
size_hint_y: None
# The column heading labels have their width set by the parent,
# but determine their height from the text.
<HeadingLabel#Label>:
bold: True
padding: dp(6), dp(4)
valign: 'bottom'
height: self.texture_size[1]
text_size: self.width, None
size_hint_y: None
<ToggleButton,Button>:
padding: dp(10), dp(8)
size_hint: None, None
size: self.texture_size
# This inherits Button and the modifications above, so reset size
<Spinner>:
size: sp(68), self.texture_size[1]
<DemoLabel#Label>:
halign: app.halign
valign: app.valign
shorten: app.shorten
max_lines: app.max_lines
canvas:
Color:
rgb: 68/255.0, 164/255.0, 201/255.0
Line:
rectangle: self.x, self.y, self.width, self.height
<StackLayout>:
size_hint_y: None
spacing: dp(6)
padding: dp(6), dp(4)
height: self.minimum_height
TYIA
Have a look at the screenshot below:
I kinda new in this Kivy layout scheme, previously I work a lot in PyQt. In PyQt, that blank vertical space can easily get rid of by using Spacer. But how do you do this in Kivy? Below is part of the KV file that constitute this layout.
GridLayout:
cols: 1
GridLayout:
cols: 2
row_default_height: '48dp'
row_force_default: True
spacing: 10, 10
padding: 10, 10
Label:
size_hint: None, None
text: 'Input'
halign: 'left'
valign: 'top'
text_size: self.size
width: 50
TextInput:
id: txt_url
size_hint: 1, None
text: ''
TabbedPanel:
id: tp
do_default_tab: False
TabbedPanelItem:
id: tab_fl
text: ''
TabbedPanelItem:
text: ''
FloatLayout
id: box
TabbedPanelItem:
text: ''
FloatLayout
id: box
I Would love to know what is the best practice of using Kivy layout mechanism. :)
In this case, you can take advantage of the GridLayout's minimum_height property to size it appropriately.
GridLayout:
cols: 1
GridLayout:
cols: 2
row_default_height: '48dp'
row_force_default: True
spacing: 10, 10
padding: 10, 10
# add these two lines
size_hint_y: None
height: self.minimum_height
...
Because you're using one column width in your root GridLayout, it be possible to resize the rows based off children height using the following trick for setting rows_minimum.
GridLayout:
cols: 1
row_force_default: True
## Call it what ya like, just interested in setting 'self.rows_minimum'
foo: [self.rows_minimum.update({i: x.height}) for i, x in enumerate(reversed(list(self.children)))]
## ... rest of layout ...
The internal GridLayout and TabbedPanel are the rows/children of your root GridLayout, so setting heights for the internal elements should allow for the foo generator redirection to pull-up the excess space.
Now for readers that may have more than one column there be a more extensive example, that shows one way of handling auto-sizing of grid layouts and a bunch of other goodies, over at another answer regarding text input word wrapping.