Kivy ScrollView is not able to scroll - python

This is the .py file:
from kivy.app import App
from kivy.uix.button import Button
from kivy.uix.scrollview import ScrollView
from kivy.uix.stacklayout import StackLayout
class Stack(StackLayout):
def __init__(self,**kwargs):
super().__init__(**kwargs)
for i in range(0,100):
b1 = Button(text=str(i+1),size_hint=(.1,.1))
self.add_widget(b1)
class ScrollView(ScrollView):
pass
class GameApp(App):
def build(self):
return Stack()
GameApp().run()
And this is the .kV file:
<ScrollView>:
Stack:
size_hint:1,None
height:4000
In the output I am getting the buttons but I am unable to scroll.

Hello if you are new please check this link for beginners guide.
The ScrollView only works if you put 1 widget on it with specific adjustments to size ofcourse.
Instead of this line
return stack()
You must return the scrollview widget and add the stack() layout on top. Even better you can modify your code like so
For .py
from kivy.app import App
from kivy.uix.button import Button
from kivy.uix.scrollview import ScrollView
from kivy.uix.stacklayout import StackLayout
from kivy.uix.screenmanager import Screen
class MainScreen(Screen):
pass
class Stack(StackLayout):
def __init__(self,**kwargs):
super().__init__(**kwargs)
for i in range(0,100):
b1 = Button(text=str(i+1),size_hint=(.1,.1))
self.add_widget(b1)
class GameApp(App):
def build(self):
return MainScreen()
GameApp().run()
.kv
<MainScreen>:
ScrollView:
do_scroll_y: True
do_scroll_y: False
Stack:
size_hint:1,None
height:4000
I did not test the code but thats the logic of how the code can be. The rest you can check here

Related

Python/Kivy Multiple screens not working, Code does not recognise the screen manager?

I am trying to make an app that starts in the main menu, you press the play button and it sends you to the game on a different screen.
Problem is i keep getting an error on the:
"kv= Builder.load_file("my.kv")" saying that "WindowManager" is an unknown class.
import kivy
from kivy.app import App
from kivy.uix.widget import Widget
from kivy.lang.builder import Builder
from kivy.uix.screenmanager import Screen, ScreenManager
from kivy.vector import Vector
from kivy.uix.floatlayout import FloatLayout
kv= Builder.load_file("my.kv")
class WindowManager(ScreenManager):
pass
class MenuWindow(Screen):
pass
class Game(Screen):
pass
class MyApp(App):
def build(self):
return kv
if __name__ == "__main__":
MyApp().run()
AND HERE IS THE KV FILE:
WindowManager:
MenuWindow:
Game:
<MenuWindow>:
name: "Menu"
FloatLayout:
Button:
text:"Play"
on_release:
app.root.current= "Game"
<Game>:
name: "Game"

how to access an id from one class in another class

i want to access an id from class main to class fahim2_pop. want to access to word from textinput(in main class) to the popup widget which will appear when someone press the search button. when someone search "hello" and press search button the the popup widget will appear and in that popup widget the text of the label will be "hello" same as from the textinput. but the label and the id remains in different class. how to do it?
python code
from kivy.app import App
from kivy.uix.boxlayout import BoxLayout
from kivy.lang import Builder
from kivy.uix.popup import Popup
from kivy.properties import *
class fahim2_pop(Popup):
pass
class main(BoxLayout):
def word(self):
pop=fahim2_pop()
pop.open()
class go(BoxLayout):
def main(self):
self.clear_widgets()
self.add_widget(main())
class CallApp(App):
def build(self):
return go()
CallApp().run()
kv code
Builder.load_string('''
<main>:
BoxLayout:
orientation:"vertical"
TextInput:
id:word
Button:
text:"search"
on_press:root.word()
<go>:
Button:
text:"go"
on_press:root.go()
<fahim2_pop>:
id:pop
title:"result"
BoxLayout:
Label:
text:app.root.ids.word.text
''')
i know app.root.ids.word.text if that id remain in root of my app. but here go is the root of app. how to access id from class main in class fahim2_pop?
There are a couple of ways of solving this problem. One of the solution is as follow:
py file
Rename method main() in class go() to go() because in your kv file, you have binded on_press: root.go()
Instantiate main() and store it in a class attribute, main
Snippets - py file
from kivy.properties import ObjectProperty
...
class go(BoxLayout):
main = ObjectProperty(None) # declare class attribute
def go(self):
self.clear_widgets()
self.main = main()
self.add_widget(self.main)
kv file
Replace text:app.root.ids.word.text with text:app.root.main.ids.word.text
Snippets - kv file
<fahim2_pop>:
...
Label:
text:app.root.main.ids.word.text
Example - main.py
from kivy.app import App
from kivy.uix.boxlayout import BoxLayout
from kivy.lang import Builder
from kivy.uix.popup import Popup
from kivy.properties import ObjectProperty
Builder.load_string('''
<main>:
BoxLayout:
orientation:"vertical"
TextInput:
id:word
Button:
text:"search"
on_press:root.word()
<go>:
Button:
text:"go"
on_press:root.go()
<fahim2_pop>:
id:pop
title:"result"
BoxLayout:
Label:
text:app.root.main.ids.word.text
''')
class fahim2_pop(Popup):
pass
class main(BoxLayout):
def word(self):
pop = fahim2_pop()
pop.open()
class go(BoxLayout):
main = ObjectProperty(None)
def go(self):
self.clear_widgets()
self.main = main()
self.add_widget(self.main)
class CallApp(App):
def build(self):
return go()
CallApp().run()
Output

Unable to switch screens using kivy language

I am new to Kivy language. I am trying build a simple program to switch between two screens. First screen with contain a button which on_release it will switch to second screen. On clicking the button on second screen will get to first screen.
Issues i face:
1. Button is placed on the corner and i am expecting its size to be full window but it small
On click and release the button doesnt' show any effect.
Chat.kv
<ChatGUI>:
MainManager:
MainWindow:
SecondWindow:
<MainWindow>:
name: "main"
Button:
text:"to second window"
on_release:app.root.current="second"
<SecondWindow>:
name: "second"
Button:
text:"back to main"
on_release:app.root.current="main"
python code:
from kivy.app import App
from kivy.uix.label import Label
from kivy.uix.widget import Widget
from kivy.uix.gridlayout import GridLayout
from kivy.uix.textinput import TextInput
from kivy.uix.button import Button
from kivy.uix.scrollview import ScrollView
from kivy.graphics import Rectangle, Color, Canvas
from kivy.uix.screenmanager import ScreenManager,Screen
from kivy.core.window import Window
from kivy.config import Config
from kivy.lang import Builder
class ChatGUI(Widget):
present=Builder.load_file("Chat.kv")
class MainWindow(Screen):
pass
class SecondWindow(Screen):
pass
class MainManager(ScreenManager):
pass
class ChatApp(App):
def build(self):
return ChatGUI()
if __name__=="__main__":
ChatApp().run()
My output# i am not able to add image so posted link of output
I am practicing from youtube tutorial.
I have checked many codes from stack overflow and i don't see issues in my code.
output should display button of size occupying whole window and on_release it should switch to next screen.
Can you let me know what could be issue.
You do not need to add a ScreenManager inside a Widget.
So
class ChatGUI (ScreenManager):
in python file and
<ChatGUI>:
     MainWindow:
     SecondWindow:
in kv file
that's all I changed to make your example work.
Chat.kv
<ChatGUI>:
MainWindow:
SecondWindow:
<MainWindow>:
name: "main"
Button:
text:"to second window"
on_release:app.root.current="second"
<SecondWindow>:
name: "second"
Button:
text:"back to main"
on_release:app.root.current="main"
main.py
from kivy.app import App
from kivy.uix.label import Label
from kivy.uix.widget import Widget
from kivy.uix.gridlayout import GridLayout
from kivy.uix.textinput import TextInput
from kivy.uix.button import Button
from kivy.uix.scrollview import ScrollView
from kivy.graphics import Rectangle, Color, Canvas
from kivy.uix.screenmanager import ScreenManager,Screen
from kivy.core.window import Window
from kivy.config import Config
from kivy.lang import Builder
class ChatGUI(ScreenManager):
present=Builder.load_file("Chat.kv")
class MainWindow(Screen):
pass
class SecondWindow(Screen):
pass
class ChatApp(App):
def build(self):
return ChatGUI()
if __name__=="__main__":
ChatApp().run()
Problem 1 - widget # bottom left hand corner & not full window?
Button is placed on the corner and i am expecting its size to be full
window but it small
Root Cause
The Button widget appeared on the bottom left hand corner because the root is a Widget and no position (pos, or pos_hint) was provided. Therefore, the default position of (0, 0) was used.
The size is not a full window because by default the size of a Widget is (100 x 100) or the default size_hint is (1, 1).
Kivy Widget » Default values
A Widget is not a Layout: it will not change the position or the size of its children. If you want control over positioning or
sizing, use a Layout.
The default size of a widget is (100, 100). This is only changed if the parent is a Layout. For example, if you add a Label inside a
Button, the label will not inherit the button’s size or position
because the button is not a Layout: it’s just another Widget.
The default size_hint is (1, 1). If the parent is a Layout, then the widget size will be the parent layout’s size.
Problem 2 - on release button screen not switched?
On click and release the button doesnt' show any effect.
Root Cause
The screen was not switched when button press was released, because the root of the App is not a ScreenManager.
Solution
There are two options to the problems.
Option 1 - use Layout as root
This option use BoxLayout as the root and requires the following enhancements. A Layout can be a GridLayout, BoxLayout, FloatLayout, etc.
Py file
Replace Widget with BoxLayout
Replace present = Builder.load_file(...) with Builder.load_file(...)
Move Builder.load_file(...) out of class ChatGUI() and add pass
kv file
Add id: sm under instantiated object, MainManager:
Replace app.root.current with app.root.ids.sm.current
Snippets - Option 1
main1.py
from kivy.app import App
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.screenmanager import ScreenManager, Screen
from kivy.lang import Builder
Builder.load_file("main1.kv")
class ChatGUI(BoxLayout):
pass
class MainWindow(Screen):
pass
class SecondWindow(Screen):
pass
class MainManager(ScreenManager):
pass
class ChatApp(App):
def build(self):
return ChatGUI()
if __name__ == "__main__":
ChatApp().run()
main1.kv
<ChatGUI>:
MainManager:
id: sm
MainWindow:
SecondWindow:
<MainWindow>:
name: "main"
Button:
text: "to second window"
on_release: app.root.ids.sm.current="second"
<SecondWindow>:
name: "second"
Button:
text: "back to main"
on_release: app.root.ids.sm.current="main"
Option 2 - use ScreenManager as root
This option requires the following enhancements:
Py file
Remove import statement, from kivy.uix.widget import Widget
Remove class ChatGUI()
Replace return ChatGUI() with return MainManager()
Replace present = Builder.load_file(...) with Builder.load_file(...)
kv file
Remove class rule, : in the kv file
Replace MainManager: with class rule, :
Snippets - Option 2
main2.py
from kivy.app import App
from kivy.uix.screenmanager import ScreenManager, Screen
from kivy.lang import Builder
Builder.load_file("main2.kv")
class MainWindow(Screen):
pass
class SecondWindow(Screen):
pass
class MainManager(ScreenManager):
pass
class ChatApp(App):
def build(self):
return MainManager()
if __name__ == "__main__":
ChatApp().run()
main2.kv
<MainManager>:
MainWindow:
SecondWindow:
<MainWindow>:
name: "main"
Button:
text: "to second window"
on_release: app.root.current="second"
<SecondWindow>:
name: "second"
Button:
text: "back to main"
on_release: app.root.current="main"

Kivy reStructuredText renderer popup?

i want popup effect for references in kivy reStructuredText renderer, in default when we press any reference it scrolls to the reference, here i want to replace scroll with a popup, i have been searching for this for a long time but in vain, today i found goto(ref, *largs)in kivy docs, is it possible to call a reference popup using this? is it possible to redefine RstDocument fuctions in another class and use it?? i am a beginner.
from kivy.app import App
from kivy.uix.boxlayout import BoxLayout
from kivy.lang import Builder
Builder.load_string("""
<RSTGUI>:
RstDocument:
text: root.doc
goto: # Any Popup aur bubble with reference
""")
class RSTGUI(BoxLayout):
doc="""
.. _top:
Hello world
===========
This is an **emphased text**, some ``interpreted text``.
And this is a reference to top_::
$ print("Hello world")
"""
class RST(App):
def build(self):
return RSTGUI()
if __name__=='__main__':
RST().run()
After little research i have figured it out, Alhumdolillah.
from kivy.app import App
from kivy.uix.boxlayout import BoxLayout
from kivy.lang import Builder
from kivy.uix.rst import RstDocument
from kivy.uix.popup import Popup
Builder.load_string("""
<RSTGUI>:
MyRST:
text: root.doc
<about_us_popup>:
size_hint: 0.8,0.6
title: "About Us"
BoxLayout:
orientation:'vertical'
RstDocument:
text: "MyText"
Button:
text:"OK"
size_hint: 1,0.1
on_press:root.dismiss()
""")
class RSTGUI(BoxLayout):
doc="""
.. _top:
Hello world
===========
This is an **emphased text**, some ``interpreted text``.
And this is a reference to top_::
$ print("Hello world")
"""
class MyRST(RstDocument):
def __init__(self, **kwargs):
super(MyRST, self).__init__(**kwargs)
self.about_us_popup = about_us_popup()
def goto(self, ref, *largs):
self.about_us_popup.open()
class RST(App):
def build(self):
return RSTGUI()
class about_us_popup(Popup):
pass
if __name__=='__main__':
RST().run()

Trouble connecting objects in .kv file to python class

I am learning Kivy and having trouble connecting my objects declared in the .kv file to the python class in order to update their properties. No matter which way I try I get this error:
self.kbCompressionLabel.text = 'Hello World'
AttributeError: 'NoneType' object has no attribute 'text'
The app loads all the kivy files fine, and only breaks when I try to update from the Class.
I've dumbed down the current code to the minimum to illustrate how it is setup. Any help is much appreciated.
Main app entry
import kivy
kivy.require('1.10.0')
from kivy.app import App
from kivy.lang import Builder
from kivy.uix.screenmanager import ScreenManager
Builder.load_file('appscreenmanager.kv')
Builder.load_file('compressorscreen.kv')
Builder.load_file('slidersview.kv')
class AppScreenManager(ScreenManager):
pass
class AppManager(App):
def build(self):
return AppScreenManager()
if __name__ == "__main__":
AppManager().run()
Dumed down appscreenmanager.kv
#:kivy 1.10.0
<AppScreenManager>:
CompressorScreen:
...
compressorscreen.kv
<CompressorScreen>:
name: 'compressor'
GridLayout:
rows: 4
cols: 1
SlidersView:
...
This is where the issue is happening: simplified slidersview.kv
#:kivy 1.10.0
#:import slidersview slidersview
<slidersView>:
cols: 4
rows: 2
id: sliders
kbCompressionLabel: kbCompressionLabel
Label:
id: kbCompressionLabel
text: 'test'
slidersview.py
import kivy
kivy.require('1.10.0')
from kivy.uix.gridlayout import GridLayout
from kivy.properties import ObjectProperty
class SlidersView(GridLayout):
# properties
sliders = ObjectProperty(None)
kbCompressionLabel = ObjectProperty(None)
def __init__(self, **kwargs):
self.kbCompressionLabel.text = 'Hello World'
super(SlidersView, self).__init__(**kwargs)
UPDATE
I had to add a delay into the init function then things worked. However, this feels pretty wonky to me. Is this the expected behavior?
Updated slidersview.py
import kivy
kivy.require('1.10.0')
from kivy.clock import mainthread
from kivy.uix.gridlayout import GridLayout
from kivy.properties import ObjectProperty
class SlidersView(GridLayout):
# properties
kbCompressionLabel = ObjectProperty(None)
def __init__(self, **kwargs):
super(SlidersView, self).__init__(**kwargs)
#mainthread
def delayed():
self.kbCompressionLabel.text = 'Hello World'
delayed()
The KV definitions are applied only when you call __init__ of the base classes...
reverse the order and you'll be fine...
class SlidersView(GridLayout):
# properties
sliders = ObjectProperty(None)
kbCompressionLabel = ObjectProperty(None)
def __init__(self, **kwargs):
super(SlidersView, self).__init__(**kwargs) #first!
self.kbCompressionLabel.text = 'Hello World' #2nd!

Categories