Usage of kivy layouts - python

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

Related

How to change label text value in another screen in kivy

So I was making an online tic tac toe game using Kivy/KivyMD and im kinda stuck here trying to edit the value of a label of another screen.
here is the main.py
from kivy.lang import Builder
from kivymd.app import MDApp
from kivy.uix.screenmanager import ScreenManager, Screen
from requests import get
ip = get('https://api.ipify.org').text
class OptionScreen(Screen):
pass
class JoinServer(Screen):
pass
class CreateServer(Screen):
pass
class WindowManager(ScreenManager):
pass
class TicTacToeApp(MDApp):
def __init__(self, **kwargs):
self.title = "TicTacToe Online"
super().__init__(**kwargs)
def build(self):
TicTacToeApp.build.kv = Builder.load_file('styles\main.kv')
self.theme_cls.theme_style = "Dark"
self.theme_cls.primary_palette = "Gray"
return TicTacToeApp.build.kv
def join(self):
TicTacToeApp.build.kv.current = 'join'
def create(self):
TicTacToeApp.build.kv.current = 'create'
if __name__ == "__main__":
TicTacToeApp().run()
This is the main.kv file:
#:kivy 2.0.0
WindowManager:
OptionScreen:
name: 'option'
JoinServer:
name: 'join'
CreateServer:
name: 'create'
<OptionScreen>:
MDCard:
size_hint: None, None
size: 700, 500
pos_hint: {"center_x": 0.5, "center_y": 0.5}
elevation: 10
spacing: 25
padding: 25
orientation: 'vertical'
MDLabel:
text: "Choose an option"
font_size: "28"
padding_y: 15
size_hint_y: None
halign: 'center'
pos_hint: {'center_x': 0.5,'center_y':0.5}
MDRoundFlatButton:
text:"Join Server"
font_size: 20
pos_hint: {'center_x':0.5}
on_press: app.join()
MDRoundFlatButton:
text:"Create Server"
font_size: 20
pos_hint: {'center_x':0.5}
on_press: app.create()
Widget:
size_hint_y: None
height: 90
<JoinServer>:
MDCard:
size_hint: None, None
size: 700, 500
pos_hint: {"center_x": 0.5, "center_y": 0.5}
elevation: 10
spacing: 25
padding: 25
orientation: 'vertical'
MDLabel:
text: "Join Server"
font_size: "28"
padding_y: 15
size_hint_y: None
halign: 'center'
pos_hint: {'center_x': 0.5,'center_y':0.5}
Widget:
size_hint_y: None
height: 325
<CreateServer>:
MDCard:
size_hint: None, None
size: 700, 500
pos_hint: {"center_x": 0.5, "center_y": 0.5}
elevation: 10
spacing: 25
padding: 25
orientation: 'vertical'
MDLabel:
text: "Create Server"
font_size: 40
padding_y: 15
size_hint_y: None
halign: 'center'
pos_hint: {'center_x': 0.5,'center_y':0.5}
MDLabel:
text: "Server Address: "
id: address
font_size: 18
size_hint_y: None
halign: 'center'
pos_hint: {'center_x': 0.5,'center_y':0.5}
MDTextField:
mode: 'round'
id: passw
hint_text: "Password"
size_hint_x: None
width: 150
font_size: 18
pos_hint: {'center_x': 0.5}
MDRoundFlatButton:
text:"Create Server"
font_size: 20
pos_hint: {'center_x': 0.5}
on_press: app.create_s()
Widget:
size_hint_y: None
height: 20
I want to change the text of the label with the id address in the CreateServer screen to something else as soon as i switch to the CreateServer screen.
I was also wondering how to carry out a code as soon as you switch screens in kivy.
To change the label with the id address in the CreateServer screen simply go the
CreateServer class and do the following changes.
class CreateServer(Screen):
def on_enter(self, *args):
self.manager.get_screen("create").ids.address.text = "your new text value"
and to carry out a code when u switch screens.
use the on_enter function which was used in the answer above. the on_enter function is triggered as soon as the screen becomes active.
I hope it answered your question.

How do I align text inside a kivy label within a .kv file?

I try to make a gui for a text based RPG, and now I want to align the text of some labels to the top left, but "halign:" and "valign:" don't seem to do anything.
So how do I align the text inside my labels? Is there something I have done horribly wrong?
This is how the GUI looks at this moment and I marked where the text should be with green arrows:
This is how my .kv file looks:
BoxLayoutExample:
<BackgroundColor#Widget>:
background_color: 1,1,1,1
canvas.before:
Color:
rgba: root.background_color
Rectangle:
size: self.size
pos: self.pos
<BackgroundLabel#Label+BackgroundColor>:
background_color: 0, 0, 0, 0
<BoxLayoutExample>:
orientation: "vertical"
BoxLayout:
orientation:"horizontal"
BackgroundLabel:
background_color: 1,0,0,1
text: "Placeholder Text\nTEST\nTEST\nTEST\nTEST\nTEST\nTEST\nTEST\nTEST\nTEST\nTEST\nTEST\nTEST\nTEST"
halign: "left"
valign: "top"
font_size: "10sp"
size_hint: .5, 1
Label:
text: "Placeholder Map/Enemy #TEST TEST TEST TEST TEST \nTEST\nTEST\nTEST\nTEST\nTEST\nTEST\nTEST\nTEST\nTEST\nTEST\nTEST\nTEST\nTEST"
halign: "left"
valign: "top"
size_hint: 1, 1.3
BoxLayout:
orientation:"vertical"
size_hint: .5, 1
Label:
background_color: 1,1,1,.5
text: "Placeholder Stats\nHP\nMP\nDMG\nXP\nLVL"
halign: "left"
valign: "top"
size_hint: 1, .3
ScrollView:
size_hint: 1, .7
scroll_distance: 100
Label:
text: "Placeholder Inventory\nTEST\nTEST\nTEST\nTEST\nTEST\nTEST\nTEST\nTEST\nTEST\nTEST\nTEST\nTEST\nTEST\nTEST\nTEST\nTEST\nTEST\nTEST\nTEST\nTEST\nTEST\nTEST\nTEST\nTEST\nTEST\nTEST\nTEST\nTEST\nTEST\nTEST\nTEST\nTEST\nTEST\nTEST\nTEST\nTEST\nTEST\nTEST\nTEST"
size_hint: None, None
size: self.texture_size
halign: "left"
valign: "top"
BoxLayout:
orientation: "horizontal"
size: "60dp","60dp"
size_hint: None,None
Label:
size: "60dp","60dp"
size_hint: None,None
Button:
text: "go\nnorth"
size: "60dp","60dp"
size_hint: None,None
Label:
size: "60dp","60dp"
size_hint: None,None
BoxLayout:
orientation: "horizontal"
size: "180dp","60dp"
#pos: "0dp","60dp"
size_hint: None,None
Button:
text: "go\nwest"
size: "60dp","60dp"
#pos: "0dp","60dp"
size_hint: None,None
pos_hint: {"x":0}
Button:
text: "go\nsouth"
size: "60dp","60dp"
size_hint: None,None
Button:
text: "go\neast"
size: "60dp","60dp"
#pos: "0dp","60dp"
size_hint: None,None
Label:
size: "60dp","60dp"
size_hint: None,None
Button:
text: "use\nitem"
size: "60dp","60dp"
size_hint: None,None
Button:
text: "equip\ngear"
size: "60dp","60dp"
size_hint: None,None
Button:
text: "unequip\ngear"
size: "60dp","60dp"
size_hint: None,None
Thanks for your help, I really appreciate it.
You need to add this argument in your label:
text_size: self.size
Then the halign and valign arguments will work properly, for example:
Label:
text: "Placeholder Map/Enemy #TEST TEST TEST TEST TEST \nTEST\nTEST\nTEST\nTEST\nTEST\nTEST\nTEST\nTEST\nTEST\nTEST\nTEST\nTEST\nTEST"
text_size: self.size
halign: "left"
valign: "top"
size_hint: 1, 1.3
More details in the official kivy documentation.

How to change the image source in kivy?

I am trying to make an app that shows one image. When I click in some button, the function will change the source of this image, therefore this image will change. So, I tried only change the line image.source, I think the correct way to do this is using a stringproperty, but I also have not had success with it. So, my code is:
.py
class PrimeiroScreen(Screen):
def __init__(self, **kwargs):
self.name = 'um'
super(Screen,self).__init__(**kwargs)
fonte = StringProperty('cafe.jpg')
def fc1(self):
self.ids.image.source = (fonte)
self.ids.image.fonte = "cafe.jpg"
#self.ids.image.source = "cafe.jpg"
class MyImage(Image):
fonte = StringProperty()
class RootScreen(ScreenManager):
pass
and .kv:
<RootScreen>:
PrimeiroScreen:
<PrimeiroScreen>:
StackLayout:
orientation: 'tb-rl'
ScrollView:
#size: 100, 100
#pos_hint: {'center_x': .5, 'center_y': .5}
GridLayout:
cols: 1
padding: 10, 10
spacing: 5, 5
size_hint: (None, None)
size_hint_y: None
width: 500
height: self.minimum_height
Button:
text: "1"
#color: 0,0,0,1
font_size: '20dp'
size: (200, 40)
size_hint: (None, None)
on_release: root.fc1()
AnchorLayout:
Image:
source:'logo.jpg'
id: image
I am learning about AnchorLayout, and StackLayout, so it's not working.
Very thanks everyone, for awser my newbie question. Nice weekend.
The thing is with your current code there is no fonte defined(at least for me with copy&paste), you need to use self.fonte.
But anyway, you should access the source directly, otherwise you'd need to make another function that handles your property updating and doing something when it changes i.e. passing it to source, which already is a StringProperty, therefore you'd go really around the solution until you reached it.
<RootScreen>:
PrimeiroScreen:
<PrimeiroScreen>:
StackLayout:
orientation: 'tb-rl'
ScrollView:
#size: 100, 100
#pos_hint: {'center_x': .5, 'center_y': .5}
GridLayout:
cols: 1
padding: 10, 10
spacing: 5, 5
size_hint: (None, None)
size_hint_y: None
width: 500
height: self.minimum_height
Button:
text: "1"
color: 0,0,0,1
font_size: '20dp'
size: (200, 40)
size_hint: (None, None)
on_release: image.source='newcafe.png'
MyImage:
source: 'cafe.jpg'
id: image

kivy referencing from a different class

Please how do I reference a member of class A in class B
Builder.load_string("""
<Main>
do_scroll_x: True
do_scroll_y: False
bar_width: 20
padding: 10
Carousel:
id: caro_slider
#direction: 'top'
padding: 10
orientation: 'vertical'
BoxLayout:
padding: 10
orientation: 'vertical'
Label:
text: "one two three"
Button:
text: 'Next'
background_color: 1, 0.1 ,0.1, 1
pos_hint: {'right': 1}
size_hint: None, None
size: '74sp', '35sp'
on_press: caro_slider.load_next()
BoxLayout:
orientation: 'vertical'
Label:
text: "five six seven"
Button:
text: "Click me"
background_color: 1, 0.1 ,0.1, 1
on_press: root.show_popup_item()
size_hint: .6, .2
pos_hint: {'center_x': 0.5, 'bottom': 1}
BoxLayout:
orientation: 'horizontal'
size_y: '35sp'
size_hint: 1, 0
Button:
text: 'Previous'
pos_hint: {'left': 1}
size_hint: None, None
size: '74sp', '35sp'
on_press: caro_slider.load_previous()
Button:
text: 'Next'
background_color: 1, 0.1 ,0.1, 1
pos_hint: {'right': 1}
size_hint: None, None
size: '74sp', '35sp'
on_press: caro_slider.load_next()
BoxLayout:
orientation: 'vertical'
size_hint: 1, None
Label:
text: "Please choose your choice"
size_hint: None, None
Label:
text: ''
size_hint: None, None
GridLayout:
orientation: 'horizontal'
size_hint: 1, None
rows: 1
row_force_default: True
row_default_height: '35sp'
CheckBox:
id: chk_box_4
height: '35sp'
group: root.group_list
size_hint: None, None
on_active: root.chk_chk(self)
Label:
text: "Four over there"
height: '35sp'
size_hint: None, None
Button:
text: 'Previous'
background_color: 1, 0.1 ,0.1, .5
pos_hint: {'left': 1}
size_hint: None, None
size: '74sp', '35sp'
on_press: caro_slider.load_previous()
# the popup
<Pops>
title: "Welcome!"
auto_dismiss: False
background_color: 0.1, 0.1 , 0.8, 0.9
size: 400, 250
size_hint: None, None
title_height: '40sp'
separator_height: '1sp'
separator_color: 1,1,1,1
BoxLayout:
orientation: 'vertical'
Label:
text: "Thanks and praises"
id: sub_title
max_lines: 5
size_hint: None, None
pos_hint: {'center_y': 0, 'center_x': 0}
Label:
id: composition
text: "Thanks be to GOD for this to [ref=work]work[/ref] and not to work."
markup: True
size_x: self.parent.size[0]
on_ref_press: print 'clicked the link', self.ids.caro_slider.slides ------> here is the problem
Button:
id: close_button
text: "Click to close"
background_color: 1, 0.1 ,0.1, 1
size_hint: .5, .5
pos_hint: {'center_x': 0.5}
on_press: root.dismiss()
""")
You need some reference to class A from class B. A simple general way to do it is to store the reference in your App class (i.e. App.get_running_app().classa = a) then reference it with App.get_running_app().classa. In specific cases there might be better places to put it than cluttering up your App though, for instance in the common parent of both class instances.

Kivy: ScrollViewApp example in Kivy Language

I'm having trouble with going back and forth between the concepts in the Kivy language, vs. Python language. I'm not very good at explaining things, and i've thought about how to explain my specific problem, but the best way i can think to do that is:
How would one implement the ScrollViewApp using the Builder function?
hm, something like
ScrollView:
size_hint: None, None
size: 500, 320
pos_hint: {'center_x': .5, 'center_y': .5}
do_scroll_x: False
GridLayout:
cols: 1
padding: 10
spacing: 10
size_hint_y: None
height: self.minimum_height
ScrollButton:
text: '1'
ScrollButton:
text: '2'
ScrollButton:
text: '3'
ScrollButton:
text: '4'
ScrollButton:
text: '5'
ScrollButton:
text: '6'
<ScrollButton#Button>
size_hint: None, None
size: 480, 40
here, however we don't really have a way to dynamically create the children (well, there would be ways, but they are ugly), so i put a few manualy, idealy you would create the ScrollView and GridLayout in kv, and then put the children inside from python (using ids, as explained in the doc).
edit: more complete version using an app and ObjectProperty
kv file (scroll.kv):
ScreenManager:
Screen:
ScrollView:
size_hint: None, None
size: 500, 320
pos_hint: {'center_x': .5, 'center_y': .5}
GridLayout:
cols: 1
padding: 10
spacing: 10
height: self.minimum_height
size_hint: None, None
do_scroll_x: False
id: container
<ScrollButton>
size_hint: None, None
size: 480, 40
python file (main.py):
from kivy.app import App
from kivy.uix.button import Button
class ScrollButton(Button):
pass
class ScrollApp(App):
def build(self):
super(ScrollApp, self).build()
container = self.root.ids.container
for i in range(30):
container.add_widget(ScrollButton(text=str(i)))
return self.root # return root does not work
if __name__ == '__main__':
ScrollApp().run()

Categories