Extending the Kivy ScrollView contents down - python

I have a FloatLayout as a child of a ScrollView with size_hint_y set to None. I want to be able to extend it as I add more and more content. The problem is that since Kivy's coordinate system starts at the bottom-left, when I add to the FloatLayout height, all the content stays at the bottom. Can I somehow make it extend down? Because I don't think that moving all widgets up is efficient, especially if there's a lot of them and I need to handle the position of all children as well.
Here is a snippet that explains the problematic behaviour:
from kivy.app import App
from kivy.uix.floatlayout import FloatLayout
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.button import Button
from kivy.uix.scrollview import ScrollView
from kivy.uix.label import Label
class TestApp(App):
def extend_h(self, *args):
global msg_float
msg_float.height += 50
def build(self):
global msg_float
msg_float = FloatLayout(size_hint_y = None)
bt1_main = Button(on_press = self.extend_h)
bl = BoxLayout()
sc = ScrollView()
sc.add_widget(msg_float)
bl.add_widget(sc)
bl.add_widget(bt1_main)
lb = Label(text = "Test",
size=(100,200),
size_hint = (None, None))
msg_float.add_widget(lb)
return bl
TestApp().run()
With a press of a button, the view extends and the "Test" label stays at the bottom, but I'd want it to stay on top.

You could use a relative layout instead of a float layout to fix the coords, but instead you should just omit using any of these, and add labels to a grid layout. Check examples at kivy repo:
https://github.com/kivy/kivy/blob/master/examples/widgets/scrollview.py
https://github.com/kivy/kivy/blob/master/examples/widgets/scrollview.kv

Related

Kivy: Change popup title label proprieties

I'm writing an interface with Kivy.
I've added a change in my .kv file that remove size_hint from Label
<Label>
size_hint: None, None
This change reflects itself obviously on all labels, included the labels of all buttons and, my problem, the label of the popup title.
In fact, label of the popup title remains little and text goes to newline after few letters (you can see it easily by creating a popup with a long title and set the Label with size_hint: None, None)
I could write a custom class like MyLabel#Label but this will not reflects on all buttons, and I should rewrite all buttons, and all place where labels are used but not explicitly declared by the code.
That's why I'm looking for another way to accomplish this.
There's a way to tell to kivy, in .kv file or in my python main.py, to use a different label class for my popup title? or to set the size_hint property of the label used in the popup title?
Thanks for Your Attention,
Best Regards.
[EDIT]
Screenshot of the running example problem
Example:
my.kv
<Label>
size_hint: None, None
main.py
from kivy.app import App
from kivy.lang import Builder
from kivy.uix.screenmanager import ScreenManager, Screen
from kivy.properties import ObjectProperty
from kivy.uix.popup import Popup
from kivy.uix.label import Label
from kivy.core.window import Window
def ForceLimit():
pop = Popup(title='Force limit reached!',content=Label(text='Force limit reached! Decremental movement inhibited.'),size_hint=(None, None), size=(400, 400))
pop.open()
kv = Builder.load_file("my.kv")
class MyMainApp(App):
def build(self):
#Window.borderless = True
Window.size = (1024,600)
return ForceLimit()
if __name__ == "__main__":
MyMainApp().run()

First character not getting printed in kivy

I am learning to code in Kivy using python
But my Label is not showing the first character
Can anyone help me
The kv File is as follows:
<MyGrid>
Label:
text: "Techy Matanhelia"
The python file is as Follows:
from kivy.app import App
from kivy.uix.button import Button
from kivy.uix.gridlayout import GridLayout
from kivy.uix.textinput import TextInput
from kivy.uix.label import Label
from kivy.uix.widget import Widget
class MyGrid(Widget):
pass
class MyApp(App):
def build(self):
return MyGrid()
if __name__ == '__main__':
MyApp().run()
Also Can anyone tell me how to edit kivy files on pycharm2020.2.2
That is because your MyGrid class extends Widget. A simple Widget has no capability to handle positioning or sizing of its children, so the Label gets assigned the default size of (100,100) and the default position of (0,0). which results in the first letter of the Label being off the screen. Try making MyGrid extend a Layout, perhaps like this:
class MyGrid(FloatLayout):
pass

Adding a new Button on release of another button in Kivy

I'm trying to have a button where if it is clicked it will insert a new button. I cant get the bind to return the new button.
from kivy.base import runTouchApp
from kivy.lang import Builder
from kivy.uix.button import Button
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.floatlayout import FloatLayout
from kivy.app import App
from kivy.uix.label import Label
from kivy.uix.widget import Widget
from kivy.uix.scatter import Scatter
from kivy.uix.button import Button
class app(App):
def build(self):
layout = FloatLayout()
button1 =Button(text="test",pos=(385,450),size_hint=(.1,.1))
button1.bind(on_release=self.btn2)
layout.add_widget(button1)
return layout
def btn2(self, event):
print "worked"
layout = FloatLayout()
btn3 = Button(text="worked",size=(.1,.1),pos=(380,400))
layout.add_widget(btn3)
return layout
app().run()
You are creating another instance of FloatLayout in the btn2 event with layout = FloatLayout(), however that instance isn't anywhere else, but in the btn2 method - i.e. you added a Button to FloatLayout, but that layout isn't visible and after the function ends it's highly possible that even doesn't exist, because it's garbage-collected by Python.
You can either use partial to pass the already existing instance of FloatLayout (where your previous Button is) like this if you need only one layout:
from kivy.uix.button import Button
from kivy.uix.floatlayout import FloatLayout
from kivy.app import App
from functools import partial
class app(App):
def build(self):
layout = FloatLayout()
button1 =Button(text="test",pos=(385,450),size_hint=(.1,.1))
button1.bind(on_release=partial(self.btn2, layout))
layout.add_widget(button1)
return layout
def btn2(self, layout, *args):
print "worked"
btn3 = Button(text="worked",size=(.1,.1),pos=(380,400))
layout.add_widget(btn3)
app().run()
Or you can use the instance that's passed to method arguments from the event (the instance of a widget that dispatched the event):
from kivy.uix.button import Button
from kivy.uix.floatlayout import FloatLayout
from kivy.app import App
class app(App):
def build(self):
layout = FloatLayout()
button1 =Button(text="test",pos=(385,450),size_hint=(.1,.1))
button1.bind(on_release=self.btn2)
layout.add_widget(button1)
return layout
def btn2(self, button):
layout = button.parent # parent of the button is the "layout" from build()
btn3 = Button(text="worked",size=(.1,.1),pos=(380,400))
layout.add_widget(btn3)
app().run()
In both cases you only need to find the right instance to work with, not create another one that's not even used. Also return layout isn't necessary if you don't expect on_release to work with the layout variable (which it won't).

I want to dynamically change the color of the text in a widget in grid layout

I want to dynamically change the color of the text in a widget in grid layout.
How can i achieve that? I create a widget matrix of 6x6 and i need to blink the tile's text in the grid layout dynamically.
Its very same as your older question
I want to dynamically change the color of widget in grid Layout in kivy
just in place of background_color use color property of button . Try code below :
from kivy.app import App
from kivy.uix.gridlayout import GridLayout
from kivy.uix.button import Button
from kivy.graphics import Color
from kivy.clock import Clock
import random
class RootWidget(GridLayout):
pass
class MainApp(App):
def build(self):
parent = GridLayout(cols=6)
for i in (1,2,3,4,5,6):
for j in (1,2,3,4,5,6):
parent.add_widget(Button(text='%s%s'%(i,j)))
Clock.schedule_interval(lambda a:self.update(parent),1)
return parent
def update(self,obj):
print "I am update function"
for child in obj.children:
c=[0,random.random(),1,random.random()]
child.color=c
if __name__ == '__main__':
MainApp().run()

Kivy: Multiple items in a popup wont work

I am trying to use multiple items in a popup with kivy in python. I would
like to find out how to make this work. I am not sure if it has to do with the fact
that the script is on my phone and not made for computer.
Here is a little example script that I am asking you to help make work for future reference.
import kivy
from kivy.lang import Builder
from kivy.uix.popup import Popup
from kivy.uix.textinput import TextInput
from kivy.uix.label import Label
popup = Popup(title='Test popup',
content=Label(text='Hello world'),
TextInput(text='Hi'), #Here is what I am trying to make work
size_hint=(None, None), size=(400, 400))
So you can see it is two objects in one content of the popup. I am sure this is possible
because I've seen it on kivy apps in the appstore, but not sure how to do it myself.
The content of a Popup can only be a single widget. You cannot add two widgets like you're trying to do.
To accomplish what you're trying to do you'll have to add the label and text input to e.g. a boxlayout and then add the boxlayout to content. Here's an example that should work:
from kivy.uix.popup import Popup
from kivy.uix.textinput import TextInput
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.label import Label
box = BoxLayout()
box.add_widget(Label(text='Hello world'))
box.add_widget(TextInput(text='Hi'))
popup = Popup(title='Test popup', content=box, size_hint=(None, None), size=(400, 400))
You can achieve this using kv file.
:
orientation:'vertical'
Label:
text: 'Hello World'
Button:
text: 'Press Me'
In python file:
def openPop(self):
self.pop = Popup(title='Test',content=Content(),auto_dismiss=True)
self.pop.open()
you need to do this:
def __init__(self, **kwargs):
super().__init__(**kwargs)
self.super_box = BoxLayout(orientation = "vertical")
self.pn = TextInput(text = "projectname") # TODO: Project name input
self.super_box.add_widget(self.pn)
"""Create button: Creates a new project repo"""
cb = Button(text="Create")
cb.bind(on_release = lambda x: print("a new project repo gets created"))
self.super_box.add_widget(cb)

Categories