I am new to Kivy and struggling to change elements in MainWindow based on what happens in SecondWindow. The code below is how far I have got on my own. The clicking of the "A" button in SecondWindow fires an event in WindowManager and prints "A" in console. However, I would like to update id: labeltext in MainWindow based on that click. Can that be done directly somehow or do how do I pass information from WindowManager to MainWindow. If so, how? I am new to object oriented programming so these things cause a lot of head scratching to me. Thank you!
Python code:
from kivy.app import App
from kivy.uix.widget import Widget
from kivy.properties import ObjectProperty
from kivy.uix.label import Label
from kivy.uix.floatlayout import FloatLayout
from kivy.uix.popup import Popup
from kivy.uix.textinput import TextInput
from kivy.lang import Builder
from kivy.uix.screenmanager import ScreenManager, Screen
class MainWindow(Screen):
pass
class SecondWindow(Screen):
pass
class WindowManager(ScreenManager):
def keykey(self,whichkey):
print(whichkey)
kv = Builder.load_file("multiscreen.kv")
class MyMainApp(App):
def build(self):
return kv
if __name__ == '__main__':
MyMainApp().run()
Kivy:
WindowManager:
MainWindow:
SecondWindow:
<MainWindow>:
name: "main"
labeltext: labeltext
Label:
id: labeltext
text: "XXX"
size_hint: 0.2, 0.1
pos_hint: {"x":0.5, "y":0.8}
Button:
text: "Go Second"
size_hint: 0.1, 0.1
pos_hint: {"x":0.9, "y":0.9}
on_release:
app.root.current = "second"
root.manager.transition.direction = "left"
<SecondWindow>:
name: "second"
Button:
text: "A"
size_hint: 0.1, 0.1
pos_hint: {"x":0.5, "y":0.5}
on_release:
root.manager.keykey('A')
print("dfd")
Button:
text: "Go Main"
size_hint: 0.1, 0.1
pos_hint: {"x":0.0, "y":0.9}
on_release:
app.root.current = "main"
root.manager.transition.direction = "right"
In your kv, change the rule for the Button to include:
root.manager.get_screen('main').ids.labeltext.text = 'New Text'
Related
Here is my kivyfile.kv
WindowManager:
FirstWindow:
SecondWindow:
<FirstWindow>:
name: "first"
AnchorLayout:
anchor_x: "left"
anchor_y: "top"
BoxLayout:
cols:2
orientation: 'vertical'
size_hint: None, None
size: self.minimum_size
Button:
text: "Button 1"
size_hint: (None,None)
width:200
height:30
Button:
text: "Button2"
size_hint: (None,None)
width:200
height:30
TextInput:
id: url
multiline: False
size_hint: (None,None)
width:200
height:30
TextInput:
id: url2
multiline: False
size_hint: (None,None)
width:200
height:30
Here is my .py file:
import kivy
kivy.require('1.11.1')
from kivy.app import App
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.anchorlayout import AnchorLayout
from kivy.uix.button import Button
from kivy.core.window import Window
from kivy.lang import Builder
from kivy.uix.screenmanager import ScreenManager, Screen
class FirstWindow(Screen):
pass
class SecondWindow(Screen):
pass
class WindowManager(ScreenManager):
pass
kv=Builder.load_file('kivyfile.kv')
class Downloader(App):
def build(self):
return kv
if __name__ == '__main__':
Downloader().run()
What I am trying to achive, is to get a BoxLayout at the top left corner, which has two columns - Button and TextInput NEXT TO it. However, it only does all components one under each other. I have also a future question on how to add another BoxLayout NEXT TO the previous BoxLayout that I have. As in - how to make it be on the right side of existing BoxLayout, how to position it.
Hi I'm making an app but there's an issue occurring. There are 2 buttons each on different screens. How do I center both buttons?
1st button is in MainWindow and 2nd button is in ImportWindow.
Please check my code.
Both buttons displaying at (0,0) position. I want to set the position in the center.
this is .py file
from kivy.app import App
from kivy.uix.image import Image
from kivy.uix.widget import Widget
from kivy.uix.screenmanager import ScreenManager, Screen
class MainWindow(Screen):
pass
class ImportWindow(Screen):
pass
class WindowManager(ScreenManager):
pass
class MySplashScreenApp(App):
def build(self):
sm = ScreenManager()
sm.add_widget(MainWindow(name='main'))
sm.add_widget(ImportWindow(name='second'))
return sm
return MainWindow()
if __name__ == '__main__':
MySplashScreenApp().run()
and this is .kv file
WindowManager:
MainWindow:
ImportWindow:
<MainWindow>:
Button:
text: "Start"
font_size: 12
size: 75, 50
size_hint: None, None
pos_hint: 100, 100
on_release:
root.manager.current = "second"
root.manager.transition.direction = 'left'
<ImportWindow>:
Button:
text: "Import"
font_size: 12
size: 75, 50
size_hint: None, None
pos_hint: 100, 100
on_release:
root.manager.current = "main"
root.manager.transition.direction = 'right'
Your use of pos_hint is incorrect. As shown in the documentation, the pos_hint is a dictionary. in order to center a widget using pos_hint, you can use:
pos_hint: {'center_x':0.5, 'center_y':0.5}
I'm trying to make an app. On button click on the bottom right of the screen there appears a dialog window(popup). On "Done" click the popup window closes (close_dialog method), and a new List Item is expected to appear.
Unfortunately the error occurs on "Done" click:
AttributeError: 'DialogContent' object has no attribute 'get_screen'
Could you please tell me why does the error occur and how can I fix it?
I suppose that it is caused by the fact that DialogContent class inherits from BoxLayout (not from Screen) but I don't know how to fix it.
Code .py:
from kivy.lang import Builder
from kivy.core.window import Window
from kivymd.app import MDApp
from kivy.app import App
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.scrollview import ScrollView
from kivymd.uix.button import MDFlatButton
from kivymd.uix.dialog import MDDialog
from kivymd.uix.textfield import MDTextField
from kivy.uix.textinput import TextInput
from kivy.uix.screenmanager import Screen, ScreenManager
from kivymd.uix.list import TwoLineAvatarListItem
Window.size = (288, 511)
class GroupScreen(Screen):
pass
class DialogContent(BoxLayout):
pass
class MainScreen(Screen):
dialog = None
def show_dialog(self, *args):
'''
Create group creation popup
'''
if not self.dialog:
self.dialog = MDDialog(
title="Create new group",
type="custom",
content_cls=DialogContent(),
auto_dismiss=False
)
self.dialog.open()
def close_dialog(self, *args):
'''
Close popup on Done click
'''
self.dialog.dismiss()
self.new_window()
def new_window(self, *args):
'''
Create new group button
'''
mylist = TwoLineAvatarListItem(text = self.dialog.content_cls.textfield.text,
secondary_text = "1,2,3...")
self.mdlist.add_widget(mylist)
class test2App(MDApp):
def build(self):
sm = ScreenManager()
sm.add_widget(MainScreen(name='main'))
sm.add_widget(GroupScreen(name='group'))
scroll = ScrollView()
return sm
if __name__ == '__main__':
test2App().run()
Code .kv:
ScreenManager:
MainScreen:
GroupScreen:
<DialogContent>:
textfield: textfield
orientation: "vertical"
spacing: "12dp"
size_hint_y: None
height: "120dp"
MDTextField:
id: textfield
hint_text: "Group name"
MDFlatButton:
id: btn1
text: "Done"
text_color: self.theme_cls.primary_color
on_release: root.get_screen['main'].close_dialog()
<MainScreen>:
name: 'main'
mdlist: mdlist
FloatLayout:
size_hint: 1, 0.89
ScrollView:
MDList:
id: mdlist
MDFloatingActionButton:
pos_hint: {'right': 0.95, 'y': 0.05}
icon: "android"
theme_text_color: "Custom"
text_color: app.theme_cls.primary_color
on_release:
root.show_dialog()
<GroupScreen>:
name: 'group'
MDLabel:
text: 'Welcome'
halign: 'center'
MDRectangleFlatButton:
text: 'Back'
pos_hint: {'center_x': 0.5, 'center_y': 0.3}
on_release: root.manager.current = 'main'
Change:
on_release: root.get_screen['main'].close_dialog()
to:
on_release: app.root.get_screen('main').close_dialog()
The app.root gets you a reference to the root widget of the app, which is the ScreenManager. Then you can use get_screen('main') to access the main Screen and call its close_dialog() method.
I have this small issue where I'm trying to create a label in LabelScreen when a button in the MenuScreen is pressed. The closest I managed to do was making the Label appear in the same screen as the button.
The following code is just an simple example of what I would like to acheive. Any help is always appreciated!
.py
from kivy.app import App
from kivy.uix.floatlayout import FloatLayout
from kivy.uix.label import Label
from kivy.uix.button import Button,ButtonBehavior
from kivy.uix.image import Image
from kivy.uix.screenmanager import Screen, ScreenManager
from kivy.uix.popup import Popup
from kivy.core.window import Window
from kivy.properties import ObjectProperty, NumericProperty
class MenuScreen(Screen):
def Item1(self,button):
App.get_running_app().cart += 5
label1 = Label(text="Item 1: $5", font_size=25)
self.add_widget(label1)
class LabelScreen(Screen):
pass
class WindowManager(ScreenManager):
pass
class ExampleApp(App):
cart = NumericProperty(0)
def build(self):
return WindowManager()
if __name__ == "__main__":
ExampleApp().run()
.kv
#:import SlideTransition kivy.uix.screenmanager.SlideTransition
<WindowManager>:
MenuScreen:
LabelScreen:
<MenuScreen>:
name: "menu"
FloatLayout:
Button:
text: "Add to cart"
size_hint: 0.5,0.05
pos_hint: {"x": 0.25, "y": 0.25}
on_release:
root.Item1(self)
Label:
text: "Cart: " + str(app.cart)
font_size: 25
pos_hint: {"x": 0.25, "y": 0.25}
Button:
text: "Label Screen"
size_hint: 0.5,0.05
pos_hint: {"x": 0.25, "y": 0.1}
on_release:
app.root.transition = SlideTransition(direction = "left")
app.root.current = "label"
<LabelScreen>:
name: "label"
FloatLayout:
Label:
text: "I want Item1 Label to appear here \n instead of in the MenuScreen"
font_size: 25
pos_hint: {"x": 0, "y": 0.25}
Button:
text: "Back"
size_hint: 0.5,0.05
pos_hint: {"x": 0.25, "y": 0.1}
on_release:
app.root.transition = SlideTransition(direction = "right")
app.root.current = "menu"
You have to reference the right screen window you want to add the wiget.
Since you are adding the widget whitin the python class first we have to get the app running, then we can navigate to the screen we want:
def Item1(self,button):
App.get_running_app().cart += 5
label1 = Label(text="Item 1: $5", font_size=25)
app_running = App.get_running_app()
root_screen = app_running.root
label_screen = root_scren.get_screen('label')
label_screen.add_widget(label1)
# Or simply:
# App.get_running_app().root.get_screen('label').add_widget(label1)
I was brainstorming an idea I had for a project but the one part I got stuck at was collecting a variable from a text input box and displaying its Value as a Label in another screen, I tried putting it in a variable then just calling it as the text for the label in the kivy file but it always came back as an error, what am I doing wrong.
Kivy-
WindowManager:
Enter_Name
List
<Enter_Name>
airline: input_1
name: 'enter_name'
id: enter_nom
FloatLayout:
cols: 3
size: root.size
Label:
text: "Name of Airline?"
size_hint: 1, 0.3
pos_hint: {"x": 0, "top":1}
TextInput:
multiline: False
name: 'input_one'
id: input_1
size_hint: 0.6, 0.06
pos_hint: {"x": 0.20, "top":0.6}
Button:
size_hint: 0.2, 0.1
pos_hint: {"x": 0.4, "top":0.4}
text: "Enter"
on_release:
app.root.current = 'list'
root.line()
<List>
name: 'list'
Python -
import kivy
from kivy.app import App
from kivy.uix.widget import Widget
from kivy.uix.floatlayout import FloatLayout
from kivy.properties import ObjectProperty
from kivy.uix.screenmanager import Screen, ScreenManager
from kivy.uix.textinput import TextInput
from kivy.uix.label import Label
from kivy.lang import Builder
from kivy.uix.popup import Popup
import time
from kivy.properties import StringProperty
class Enter_Name(Screen):
input_1 = StringProperty()
def line(self):
self.gon = self.ids.input_1.text
print(self.gon)
pass
class List(Screen):
Enter_Name.line
pass
class WindowManager(ScreenManager):
pass
kv = Builder.load_file("pot.kv")
class am4(App):
def build(self):
return kv
if __name__ == "__main__":
am4().run()
Here is a modified version of your code that does what I think you want:
from kivy.app import App
from kivy.uix.screenmanager import Screen, ScreenManager
from kivy.lang import Builder
class Enter_Name(Screen):
def line(self):
App.get_running_app().root.get_screen('list').lab_text = self.airline.text
class List(Screen):
pass
class WindowManager(ScreenManager):
pass
# kv = Builder.load_file("pot.kv")
kv = Builder.load_string('''
WindowManager:
Enter_Name
List
<Enter_Name>
airline: input_1
name: 'enter_name'
id: enter_nom
FloatLayout:
cols: 3
size: root.size
Label:
text: "Name of Airline?"
size_hint: 1, 0.3
pos_hint: {"x": 0, "top":1}
TextInput:
multiline: False
name: 'input_one'
id: input_1
size_hint: 0.6, 0.06
pos_hint: {"x": 0.20, "top":0.6}
Button:
size_hint: 0.2, 0.1
pos_hint: {"x": 0.4, "top":0.4}
text: "Enter"
on_release:
app.root.current = 'list'
root.line()
<List>
lab_text: ''
name: 'list'
Label:
text: root.lab_text
''')
class am4(App):
def build(self):
return kv
if __name__ == "__main__":
am4().run()
I have added a Label to the List Screen, as well as a lab_text property that is used as the text of the Label. The line() method now just sets the value of that lab_text.
I have used load_string() instead of load_file() just for my own convenience.