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).
Related
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
getting the blank screen after running this code what is the problem
after adding .kv file everything is working fine and after removing .kv file and using the only python to show the layout it is not working
from kivy.app import App
from kivy.uix.widget import Widget
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.button import Button
class BoxLayoutExample(BoxLayout):
def __init__(self, **kwargs):
super().__init__(**kwargs)
b1 = Button(text="A")
b2 = Button(text="B")
b3 = Button(text="C")
self.clear_widgets()
self.add_widget(b1)
self.add_widget(b2)
self.add_widget(b3)
class MainWidget(Widget):
pass
class TheLabApp(App):
pass
TheLabApp().run()
This the output:)
Image
If you are not using a kv file named thelab.kv, then your App has no way of knowing what you want it to look like. You will at least need to add a build() method to your TheLabApp class that returns BoxLayoutExample().
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
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"
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