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()
Related
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
<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.
Last time I solved the error thanks to you.
However, due to my lack of skills,
I looked up a lot of data but couldn't solve the error.
If I click information Button happen this error message.
File "", line 27, in
NameError: name 'Factory' is not defined
I want to make Project. This Picture. But The Button location always not good.
This is My Python KIVY code
#project.kv file
kv = '''
BoxLayout:
orientation: 'vertical'
Upper_bar:
size_hint: (1, 0.1)
Label:
text: 'Select Mode'
BoxLayout:
padding: [90, 40]
size_hint: (1, 0.5)
orientation: 'horizontal'
Button:
size_hint: (0.5, 1)
text: 'Object'
BoxLayout:
Button:
size_hint: (0.5, 1)
text: 'Street'
<Upper_bar>:
BoxLayout:
Button:
size_hint: (0.3, 1)
text: 'Information'
on_press: Factory.InformationPop().open()
<InformationPop#Popup>:
size_hint: 0.5, 0.5
tittle: 'Information'
auto_dismiss: True
BoxLayout:
orientation: 'vertical'
Label:
text:
"""Name:
Student Number:
E-mail: """
Button:
text:
'Close'
on_press:
root.dismiss()
size_hint_y: None
height: '40dp'
'''
class Upper_bar(BoxLayout):
pass
class AIObjectCameraApp(App):
def build(self):
return Builder.load_string(kv)
if __name__ == '__main__':
AIObjectCameraApp().run()
You just forgot to add the import of Factory at the top of your kv string:
#:import Factory kivy.factory.Factory
I have this code where i want to change the position of the buttons, but if i change the position, the scroll is no longer working. How to manage to make it work? Below is the working version. If i change size_hint: 1, .1 to size_hint: 1, .7, the scroll no longer works...
from kivy.app import App
from kivy.lang.builder import Builder
from kivy.uix.floatlayout import FloatLayout
Builder.load_string('''
<Root>:
ScrollView:
size_hint: 1, .1
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()
You are doing it right. The ScrollView allows you to scroll to see parts of your GridLayout that don't fit in the ScrollView. When you set the size_hint to (1, .7), everything fits within the ScrollView, so it does not scroll.
You can force scrolling by adding Widgets to take up more space (like Labels with no text):
<Root>:
ScrollView:
size_hint: 1, .7
GridLayout:
size_hint_y: None
cols: 1
height: self.minimum_height
Label:
text: ''
size_hint_y: None
height: 300
Button
text: 'one'
size_hint: 1, None
height: self.texture_size[1]
Button:
text: 'two'
size_hint: 1, None
height: self.texture_size[1]
Button:
text: 'three'
size_hint: 1, None
height: self.texture_size[1]
Button:
text: 'four'
size_hint: 1, None
height: self.texture_size[1]
Label:
text: ''
size_hint_y: None
height: 300
Once theres a size_hint_y = None in the parent widget, then you have to manually declare the height of the child widget since size_hint_y deals with the height or Y axis.. so i modified your code to make things a lil clearer
from kivy.app import App
from kivy.lang.builder import Builder
from kivy.uix.floatlayout import FloatLayout
Builder.load_string('''
<Root>:
ScrollView:
size_hint_y:None
height:root.width / 2
GridLayout:
size_hint_y: None
cols: 1
height:self.minimum_height
spacing:dp(20)
Button
text: 'one'
size_hint_y:None
height:dp(50)
Button:
text: 'two'
size_hint_y:None
height:dp(50)
Button:
text: 'three'
size_hint_y:None
height:dp(50)
Button:
text: 'four'
size_hint_y:None
height:dp(50)
''')
class Root(FloatLayout):
pass
class DemoApp(App):
def build(self):
return Root()
if __name__ == '__main__':
DemoApp().run()
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