How to make scrollable text only in one area?Python Kivy - python

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]

Related

Usage of kivy layouts

I am using kivy to build GUI for my program. In my kv file, I want the content of the first box layout to appear on the top right and the content of the second boxlayout to appear on the top left.
Below is the my kv file.
This is not behaving as expected. Please help
<AnchorLayout>:
anchor_x: 'right'
anchor_y: 'top'
BoxLayout:
orientation: 'horizontal'
Button:
text: 'Dashboard'
size_hint: None, None
size: 80, 40
Button:
text: 'Task'
size_hint: None, None
size: 80, 40
Button:
text: 'Work'
size_hint: None, None
size: 80, 40
BoxLayout:
orientation: 'horizontal'
Label:
text: 'Logo'
Label:
text: 'MU'
The problem is that the poorly documented AnchorLayout only really works with just a single child. In your case, both of your BoxLayouts are positioned at the right, top of the AnchorLayout. However, both BoxLayouts have the default size_hint of (1,1), so they both fill the AnchorLayout, and the right top anchor has no effect.
You can use FloatLayout instead of AnchorLayout, with size_hint and pos_hint to get your desired result:
<FloatLayout>:
BoxLayout:
orientation: 'horizontal'
pos_hint: {'right':1, 'top':1}
size_hint: None, None
size: self.minimum_size
Button:
text: 'Dashboard'
size_hint: None, None
size: 80, 40
Button:
text: 'Task'
size_hint: None, None
size: 80, 40
Button:
text: 'Work'
size_hint: None, None
size: 80, 40
BoxLayout:
orientation: 'horizontal'
pos_hint: {'x':0, 'top':1}
size_hint: None, None
size: self.minimum_size
Label:
text: 'Logo'
size_hint: None, None
size: 80, 40
Label:
text: 'MU'
size_hint: None, None
size: 80, 40

Scroll does not work in kivy Layout of buttons

<Builder_Screen>
ScrollView:
do_scroll_y:True
FloatLayout:
Button:
text:"Heading"
size_hint_x: .25
size_hint_y: .25
text_size: self.size
halign:"center"
valign:"center"
pos: 0,10
Button:
text:"Paragraph"
halign:"center"
valign:"center"
size_hint_x: .25
size_hint_y: .25
pos: (0,self.height)
I have some buttons like these with positions like pos: 0, self.height2 , self.height3 etc.
But, the scroll layout does not work as intended.
Can you help me regarding that!...
According to the documentation, regarding the child of a ScrollView:
By default, the size_hint is (1, 1), so the content size will fit your
ScrollView exactly (you will have nothing to scroll). You must
deactivate at least one of the size_hint instructions (x or y) of the
child to enable scrolling.
So, you probably need to set size_hint_y: None for your FloatLayout. That will cause further problems, because you have size_hint_y values for your Buttons. You can set the heights of your Buttons and eliminate the size_hint_y values. Another approach would be to use a GridLayout:
from kivy.app import App
from kivy.lang import Builder
from kivy.uix.screenmanager import Screen
kv = '''
<Builder_Screen>
ScrollView:
do_scroll_y:True
effect_cls: 'ScrollEffect'
GridLayout:
cols: 2
size_hint_y: None
height: self.minimum_height
padding: 5
spacing: 5
Button:
text:"Heading1"
halign:"center"
valign:"center"
size_hint_y: None
height: 48
Button:
text:"Paragraph1"
halign:"center"
valign:"center"
size_hint_y: None
height: 48
Button:
text:"Heading2"
halign:"center"
valign:"center"
size_hint_y: None
height: 48
Button:
text:"Paragraph2"
halign:"center"
valign:"center"
size_hint_y: None
height: 48
Button:
text:"Heading3"
halign:"center"
valign:"center"
size_hint_y: None
height: 48
Button:
text:"Paragraph3"
halign:"center"
valign:"center"
size_hint_y: None
height: 48
'''
class Builder_Screen(Screen):
pass
class TestApp(App):
def build(self):
Builder.load_string(kv)
return Builder_Screen()
TestApp().run()
Note that every Button has an explicit height. That is required if you use height: self.minimum_height for their container.

Problem when trying to reposition images in the BoxLayout in the Kvlang

I'm creating an app with Kivy and I want it to have a header with an Image at the left corner and some buttons like a menu on this Image's right side. The problem is that I can't reposition the Image. I'm able to resize it but its position is always on the starting position of the BoxLayout.
I've tried changing its position with pos_hint and pos. Also tried resizing the Image with size_hint or setting size_hint to (None, None) and them tried to change its position again and none of them works. I've also added some buttons on the ScrollView below it that when pressed show the Image's position to check if something works.
Here is the Kvfile, I'm just pasting the Screen(SomeScreen) widget where this problem is ocurring
<SomeScreen>:
BoxLayout:
orientation: 'vertical'
BoxLayout:
id: box
size_hint: 1, 0.12
canvas:
Rectangle:
size: self.size
pos: self.pos
Image:
id: img
size_hint: None, 0.9
width: 200
pos: 200, 600
allow_stretch: True
source: 'image.png'
ScrollView:
id: scr
BoxLayout:
orientation: 'vertical'
size_hint: 1, None
height: self.minimum_height
Button:
size_hint: None, None
width: 400
height: 200
on_press: print(f'image size: {img.size}, image postion {img.pos}')
Button:
size_hint: None, None
width: 400
height: 200
on_press: print(box.size, box.pos)
Button:
size_hint: None, None
width: 400
height: 200
on_press: print(scr.size, scr.pos)
I'd like to change the image's position to whatever I choose
A couple things to note:
You are using a BoxLayout with orientation set to vertical.
That will position your widgets vertically, so the ScrollView
will not be to the right of your Image.
You have a second BoxLayout inside your first BoxLayout that
appears to serve no purpose. However, putting your Image in a
horizontal(the default) BoxLayout, means that you cannot adjust
the horizontal position of the Image
Not sure if I have captured what you intention is, but here is a modified version of your kv that, I think, is more along the lines of what you asked for:
<SomeScreen>:
BoxLayout:
Image:
id: img
size_hint: None, 0.12
width: 200
pos_hint: {'center_y':0.5}
allow_stretch: True
source: 'image.png'
ScrollView:
id: scr
BoxLayout:
orientation: 'vertical'
size_hint: 1, None
height: self.minimum_height
Button:
size_hint: None, None
width: 400
height: 200
on_press: print(f'image size: {img.size}, image postion {img.pos}')
Button:
size_hint: None, None
width: 400
height: 200
on_press: print(box.size, box.pos)
Button:
size_hint: None, None
width: 400
height: 200
on_press: print(scr.size, scr.pos)

Multiple valigns in one label

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.

Kivy (kv language) StackLayout Issue and Boundary Issue

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

Categories