Label not affected by AnchorLayout - Kivy - python

I have just started learning kivy and am stuck with this layout problem.
I used the Anchor Layout to center a button using:
Button:
text: "A button"
anchor_x:'center'
anchor_y:'center'
However when I try this:
Label:
text: "Hello World!"
size_hint: 1, 1
anchor_x:'center'
anchor_y:'top'
It just shows "Hello World!" in the default center position but I want it above my centered button.
I have tried everything and looked at the docs but have found nothing to explain this.
Edit:
Here are both files:
py file:
import kivy
kivy.require('1.8.0')
from kivy.app import App
from kivy.uix.anchorlayout import AnchorLayout
class Layout(AnchorLayout):
pass
class LayoutApp(App):
def build(self):
return Layout()
if __name__ == '__main__':
LayoutApp().run()
kv file:
<Layout>:
Label:
text: "Hello World!"
font_size: 50
size_hint: None, None
height: 100
anchor_x:'center'
anchor_y:'top'
Button:
text: "Button"
background_colour: (0,0,1,1)
size_hint: None, None
size: 50, 50
anchor_x:'center'
anchor_y:'top'

size_hint: 1, 1
This is your problem, the size_hint means the Label is the same size as the parent layout, with the text in the middle...i.e. the middle of the screen. It doesn't matter where the label is anchored, because there's no room for it to move.
You should instead manually set the size you want, e.g.
size_hint_y: None
height: 50

Related

running kivy shows black screen

I'm starting in Kivy and this small example when running it opens the screen but everything is black nothing else is seen
from kivy.app import App
from kivy.uix.boxlayout import BoxLayout
import random
class RanWindow(BoxLayout):
def __init__(self, **kwargs):
super(RanWindow, self).__init__(**kwargs)
def generate_number(self):
self.rlabel.text = str(random.randint(0, 2000))
class RandomNumber(App):
def build(self):
return RanWindow()
if __name__=="__main__":
RandomNumber().run()
random.kv
<RanWindow>:
rlabel: rlabel
BoxLayout:
orientation: "vertical"
Label:
text: "Random Number"
font_size: 30
color: 0, 0.62, 0.96
Label:
id: rlabel
text: "_"
font_size: 30
Button:
text: "Generate"
font_size: 15
on_press: root.generate_number()
does not show any error
Your random.kv file is not loaded. You need to either add:
Builder.load_file('random.kv')
to your code. Or change the name of random.kv to randomnumber.kv.

Python Kivy self.add_widget() doesn't update while code running

The idea is to create a texting app that works like Messenger. I am having a problem with the chat history which is a "BoxLayer (or GridLayer)" containing all previous text. I want when I insert a new text, it's will appear as a new label or a box and stay below the previous text like this, but when I run the code and insert input text, it's not appearing. I spent hours to find the answer both myself and on the internet, but it's kind of hard for a beginner like me.
.Py file
from kivy.app import App
from kivy.uix.widget import Widget
from kivy.uix.gridlayout import GridLayout
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.button import Button
from kivy.uix.label import Label
from kivy.core.image import Image
from kivy.properties import StringProperty
from kivy.core.window import Window
from kivy.graphics.context_instructions import Color
class MainWidget(Widget):
request = StringProperty("This is a previous text, don't mind")
insert_text = StringProperty("Insert Here")
window_size = (305,400)
refresh_key = False
def __init__(self,**kwargs):
super().__init__(**kwargs)
self.Window_Minimum()
def on_size(self,*args):
print(self.width,self.height)
def on_text_validate(self,widget): #<<<<<<<<<<<<<<<<<<<<<<<<<<< input text
request=widget.text
Chat_history_update().chat_history(request)
def Window_Minimum(self):
Window.minimum_width,Window.minimum_height=self.window_size
class Chat_history_update(BoxLayout):
def __init__(self,**kwargs):
super().__init__(**kwargs)
l = Label(text="This is a previous text, don't mind",size_hint=(1, None),height=("30dp"))
self.add_widget(l)
def chat_history(self,request): # <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< Add Label Function
l = Label(text=request, size_hint=(1, None),height=("30dp"))
self.add_widget(l) # <<<<<<<<<<<<< This won't update my app screen
class Assistant(App):
pass
if __name__ == "__main__":
Assistant().run()
Kv file
MainWidget:
<MainWidget>:
BoxLayout:
size: root.size
orientation: "vertical"
GridLayout:
cols: 3
size_hint: 1,None
height: "50dp"
spacing: "10dp"
padding: "10dp"
Label:
text:"Erza Assistant"
Button:
text:"Edit Path"
Button:
text:"Setting"
GridLayout:
size: self.size
rows: 2
spacing: "10dp"
padding: "10dp"
ScrollView: #<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< Here my text display
Chat_history_update:
orientation: "vertical"
size_hint: 1, None
height: self.minimum_height
TextInput:
size_hint: 1, None
height: "40dp"
text: root.insert_text
multiline: False
on_text_validate: root.on_text_validate(self)
Your code:
Chat_history_update().chat_history(request)
is creating a new instance of Chat_history_update, and calling chat_history() for that new instance. That new instance is not part of your GUI, so you will see no effect. The fix is to access the correct instance of Chat_history_update (the one that is in your GUI). To do that, you can add an id in your kv:
ScrollView: #<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< Here my text display
Chat_history_update:
id: chu
orientation: "vertical"
size_hint: 1, None
height: self.minimum_height
And then use that id in your py code:
def on_text_validate(self,widget): #<<<<<<<<<<<<<<<<<<<<<<<<<<< input text
request=widget.text
self.ids.chu.chat_history(request)
I think this here might help. You have to reference widgets in the kivy language by using id or ids.
If you do not yet i strongly suggest you learn how to reference widgets by their ids.

Kivy - re-focusing input field not possible?

i have the following example using kivy -
When i write something in the input field1 and press Reset - everything works fine (input field get deleted, focus on field1).
But when i am changing something in field2 and press the Reset Button it seems that the App gets broken...
Why is that and why is the statement self.ids.stockTicker.focus = True not working every time?
py-file:
import threading
from kivy.app import App
from kivy.uix.widget import Widget
from kivy.lang import Builder
from kivy.core.window import Window
Builder.load_file("TryApp.kv")
class MyLayout(Widget):
Window.size = (550, 700)
def Reset(self):
self.ids.stockTicker.text = ""
self.ids.stockTicker.focus = True
self.ids.index.text = "SP500"
def pressReset(self):
threading.Thread(target=self.Reset).start()
class MyTry(App):
def build(self):
return MyLayout()
if __name__ == "__main__":
MyTry().run()
kv-file:
<MyLayout>
BoxLayout:
orientation: "vertical"
size: root.width, root.height
GridLayout:
size_hint: (1, .5)
cols: 2
Label:
text: "Field1"
font_size: 18
TextInput:
id: stockTicker
focus: True
Label:
text: "Field2"
font_size: 18
TextInput:
id: index
text: "xyz"
Button:
id: buttonReset
text: "Reset"
#font_size: 20
on_press: root.pressReset()
size_hint: (None,None)
width: 110
height: 70
I think you just need to change:
on_press: root.pressReset()
to:
on_release: root.pressReset()
The reasoning is that when the pressReset() method is triggered by the on_press event, the focus is changed as you desire, but then the Button release event changes focus back to the Button. Changing it to the on_release event eliminates that problem.

Displaying an image over multiple buttons - kivy

I want to display a single image over multiple different buttons (as shown in the picture: https://i.stack.imgur.com/BQ99R.jpg)
When I try to do so, the image gets covered by the buttons and hidden in the background.
What I want to know is that is this even possible in kivy? If yes, where do I define the image, in the label or button?
This code:
from kivy.app import App
from kivy.uix.floatlayout import FloatLayout
from kivy.lang import Builder
Builder.load_string("""
<Base>:
GridLayout:
cols: 2
size_hint: 1, 1
Button:
text: "Button 1"
on_press: print(self.text)
Button:
text: "Button 2"
on_press: print(self.text)
Button:
text: "Button 3"
on_press: print(self.text)
Button:
text: "Button 4"
on_press: print(self.text)
Image:
source: 'wolf.png'
""")
class Base(FloatLayout):
def __init__(self, **kwargs):
super(Base, self).__init__(**kwargs)
class SampleApp(App):
def build(self):
return Base()
if __name__ == "__main__":
SampleApp().run()
produces this:
Of course you have to provide an image yourself ;o)

Scroll contents of GridLayout in ScrollView - Kivy

I will say first off I have tried every single example on the web involving kv lang. Not once have I had any success.
The idea is pretty simple: As I swipe up/down/scroll the contents of GridLayout() within ScrollView() are scrolled up or down.
The best I have been able to do is have the scroll bar fade into view when running the program. Not able to scroll unfortunately.
<Root>
grid_layout: grid_layout
ScreenManager:
...
Screen:
...
ScrollView:
GridLayout:
id: grid_layout
size_hint_y: None
cols: 1
height: self.minimum_height
<list of buttons>
Binding minimum_heightin the __init__ method of the root class (RelativeLayout):
grid_layout = ObjectProperty(None)
self.grid_layout.bind(minimum_height=self.grid_layout.setter('height'))
I have followed https://github.com/kivy/kivy/blob/master/examples/widgets/scrollview.py converting it to kv lang - scroll bar visible, unable to scroll. Also tried every example on Google Groups and here related to using kv lang. Still no scroll :\
Compiling using buildozer and running on Android fails for an unknown reason.
I would appreciate any assistance that can be given.. I am completely clueless at this point
This:
height: self.minimum_height
should be:
minimum_height: self.height
This is unnecessary:
grid_layout = ObjectProperty(None)
self.grid_layout.bind(minimum_height=self.grid_layout.setter('height'))
It also won't scroll unless the contents are larger than the scrollview's height:
Full code:
from kivy.lang.builder import Builder
from kivy.app import App
from kivy.uix.floatlayout import FloatLayout
Builder.load_string('''
<Root>:
ScrollView:
size_hint: 1, .1
# setting the width of the scrollbar to 50pixels
bar_width: 50
# setting the color of the active bar using rgba
bar_color: 5, 10, 15, .8
# setting the color of the inactive bar using rgba
bar_inactive_color: 5, 20, 10, .5
# setting the content only to scroll via bar, not content
scroll_type: ['bars']
GridLayout:
size_hint_y: None
cols: 1
minimum_height: self.height
Button
text: 'one'
Button:
text: 'two'
Button:
text: 'three'
Button:
text: 'four'
''')
class Root(FloatLayout):
pass
class DemoApp(App):
def build(self):
return Root()
if __name__ == '__main__':
DemoApp().run()
Being unable to scroll was due to a misunderstanding of Kivy's touch handlers. Completely unrelated to the code mentioned in my question.
The key is to have GridLayout be larger than ScrollView, so GridLayout can be panned within ScrollView.
For those wanting to use ScrollView inside ScreenManager using kvlang only:
ScreenManager:
id: screen_manager
Screen:
manager: screen_manager
id: main_screen
name: 'main'
ScrollView:
bar_width: 4
# pos_hint defaults to 1,1 so no need to declare it
GridLayout:
size_hint_y: None
cols: 1
# you do not need to manually bind to setter('height') in
# python - perfectly possible with kv lang
# this allows for height to update depending on the
# collective heights of its child widgets
height: self.minimum_height
<----- widgets here ----->
# for scroll to show/work there must be more widgets
# then can fit root.height. If not there is no need
# for scrollview :)

Categories