Get variable declared in another Screen - python

I am working on one simple Kivy GUI application. What i am trying to do is that i am want to access one object 'obj_random' of class 'CL_Random' from second screen(in which it is not created). I just don't know how to access declared in one screen to different screen.
from kivy.app import App
from kivy.uix.floatlayout import FloatLayout
#from kivy.uix.boxlayout import BoxLayout
#from kivy.uix.popup import Popup
from kivy.uix.screenmanager import ScreenManager, Screen
from kivy.lang import Builder
from kivy.properties import ObjectProperty
class CL_FirstWindow(Screen):
def change_screen(self):
obj_random = CL_Random()
self.parent.current = 'second_window'
class CL_SecondWindow(Screen):
scond_prop = ObjectProperty(None)
def change_screens(self):
self.parent.current = 'first_window'
class ScreenManagement(ScreenManager):
pass
class CL_Random:
def __init__(self):
self.x = 5
presentation = Builder.load_file("rough2.kv")
class app(App):
def build(self):
return presentation
obj_app = app()
obj_app.run()
rough2.kv
ScreenManagement:
CL_FirstWindow:
CL_SecondWindow:
<CL_FirstWindow>:
id: first_window_id
name: 'first_window'
FloatLayout:
Button:
text: 'Button1'
size_hint: 0.3, 0.12
pos_hint: {'x':0.1,'y':0.6}
on_release: root.change_screen()
<CL_SecondWindow>:
id: second_window_id
name: 'second_window'
FloatLayout:
Button:
text: 'Button2'
size_hint: 0.3, 0.12
pos_hint: {'x':0.1,'y':0.6}
on_release: root.change_screens()
Label:
id: second_label_id
text: 'SECOND SCREEN'
pos_hint: {'x': 0.20, 'y':0.8}
size_hint: 1, 0.1
font_size: 35
halign: 'left'
valign: 'middle'
text_size: self.size
Thnks

To access a variable that is declared within a class the first thing is that this variable must be an attribute of the class so that the scope is greater, but as in your case the variable is local and it will be eliminated when it finishes executing the function.
On the other the solution is based on accessing the other Screen via the ScreenManager, and having the object access to the attribute for it we use the get_screen() method:
CL_SecondWindow --> ScreenManager --> CL_FirstWindow --> obj_random
from kivy.app import App
from kivy.uix.screenmanager import ScreenManager, Screen
from kivy.lang import Builder
from kivy.properties import ObjectProperty
class CL_FirstWindow(Screen):
def change_screen(self):
self.obj_random = CL_Random()
self.manager.current = 'second_window'
class CL_SecondWindow(Screen):
scond_prop = ObjectProperty(None)
def change_screens(self):
first_screen = self.manager.get_screen('first_window')
print(first_screen.obj_random.x)
self.parent.current = 'first_window'
class ScreenManagement(ScreenManager):
pass
class CL_Random:
def __init__(self):
self.x = 5
presentation = Builder.load_file("rough2.kv")
class app(App):
def build(self):
return presentation
obj_app = app()
obj_app.run()

Related

How to use a global variable of str type to populate a MDLable text field. I also need to set font and size

I am ultimately trying to retrieve data from an API call to populate MDLabels. I am new to Kivy so i hope my question is not to simple but i have not found a working example after hours of searching.
import kivy
from kivymd.app import MDApp
from kivy.uix.widget import Widget
from kivy.properties import ObjectProperty
from kivymd.uix.screen import Screen
from kivymd.uix.label import MDLabel
from kivymd.uix.boxlayout import BoxLayout
from kivymd.uix.floatlayout import MDFloatLayout
from kivy.lang.builder import Builder
#Global variable from a dictionary
orch_hostName = str("some text to add to a MDLabel")
class MyGui(Screen):
orch_info = ObjectProperty(None)
def on_enter(self):
orch_info1 = orch_hostName
self.ids.orch_info.text = "orch_info1"
class MainApp(MDApp):
def build(self):
self.theme_cls.primary_palette = "Gray"
self.theme_cls.theme_style = "Light"
self.theme_cls.primary_hue = "300"
return MyGui()
if __name__ == "__main__":
MainApp().run()
##################################################
KV File
Widget:
<MyGui>
orch_info: orch_info
MDFloatLayout:
MDLabel:
id: orch_info
multiline: True
halign: 'left'
markup: True
theme_text_color: 'Custom'
text_color: (105 / 255.0, 105 / 255.0, 105 / 255.0, 1)
text: ""
font_style: 'H1'
pos_hint: {'x': .85, 'y': .47}
def __init__(self, **kwargs):
super(MyGui, self).__init__(**kwargs)
self.orch_info.text = orch_hostName
print(self.orch_info.text)

Kivy - Can't change .text with id

I am trying to change the text of a label using an id, I tried it with stringProperty, with objectProperty without any properties. There has to be something I am missing in my code because it simply does not work whatever I try and any help would be greatly appreciated.
This bit of code is a simple screen with 2 buttons, one for going to the other screen and one for changing the label
from kivy.app import *
from kivy.uix.button import *
from kivy.graphics import *
from kivy.uix.widget import *
from kivy.uix.label import *
from kivy.uix.floatlayout import *
from kivy.uix.boxlayout import *
from kivy.uix.relativelayout import *
from kivy.uix.scrollview import ScrollView
from kivy.properties import ListProperty, StringProperty,ObjectProperty
from kivy.uix.screenmanager import ScreenManager,Screen
from kivy.core.window import Window
from kivy.lang import Builder
from kivy.uix.gridlayout import GridLayout
class WindowManager(ScreenManager):
pass
class Name(FloatLayout):
def __init__(self, **kwargs):
super(Name, self).__init__(**kwargs)
def changeName(self):
print(self.ids)
self.name = self.ids.nameOfSong.text
print(self.name)
self.ids.nameOfSong.text = 'name'
self.name = self.ids.nameOfSong.text
print(self.name)
class MainWindow(Screen):
def __init__(self, **kwargs):
super(MainWindow, self).__init__(**kwargs)
self.pos = (0, 0)
self.size = (1,1)
self.z = Name()
self.add_widget(self.z)
def swap(self):
Name().changeName()
class SecondWindow(Screen,BoxLayout):
def __init__(self, **kwargs):
super(SecondWindow, self).__init__(**kwargs)
class langApp(App):
def build(self):
sm = ScreenManager()
sm.add_widget(MainWindow(name='main'))
sm.add_widget(SecondWindow(name='second'))
return sm
Builder.load_file("kiv.kv")
if __name__ == '__main__':
langApp().run()
My kiv.kv file, most of it is not connected to the problem (I think)
#:kivy 1.11.1
WindowManager:
MainWindow:
SecondWindow:
<MainWindow>:
name: "main"
FloatLayout:
pos: 0,0
size: root.width,root.height
Button:
on_release:
root.manager.transition.direction = 'left'
app.root.current = "second"
text: 'Stop'
pos_hint: {'x':.45,'y':.1}
size_hint: .1,.1
Button:
on_press: root.swap()
text: 'Next'
pos_hint: {'x':.65,'y':.1}
size_hint: .1,.1
<SecondWindow>:
name: "second"
FloatLayout:
pos: 0,0
size: root.width,root.height
Button:
on_release:
root.manager.transition.direction = 'right'
app.root.current = "main"
text: 'Stop'
pos_hint: {'x':.45,'y':.1}
size_hint: .1,.1
<Name>:
Label:
text: nameOfSong
font_size: 20
size_hint: None, None
pos_hint: {'x': 0.435, 'y': 0.25}
A few problems with your code:
First, your code as posted dos not run. The line in your kv:
text: nameOfSong
is illegal.
Second, the code:
def swap(self):
Name().changeName()
is creating a new instance of Name and calling changeName() on that new instance. However, that new instance is not the one that is displayed in your GUI.
To fix that, you just need to call changeName() on the instance of Name that is in your GUI. Conveniently, you have saved a reference to the correct instance with the line:
self.z = Name()
So, you can change the swap() method to use that instance of Name:
def swap(self):
self.z.changeName()
The other problem is that the changeName() method tries to use a non-existent id nameOfSong. To fix that (and to make your posted code runnable), just change the <Name> rule in your kv to define that id:
<Name>:
Label:
id: nameOfSong
text: 'Some Name'
font_size: 20
size_hint: None, None
pos_hint: {'x': 0.435, 'y': 0.25}
On an unrelated note, your code is building the App GUI twice. The line:
Builder.load_file("kiv.kv")
is building the GUI from the lines:
WindowManager:
MainWindow:
SecondWindow:
and your python code is building it again here:
def build(self):
sm = ScreenManager()
sm.add_widget(MainWindow(name='main'))
sm.add_widget(SecondWindow(name='second'))
return sm
You can delete those three lines from your kv file.

Outputting the input text in a new screen

Basically i'm trying to take some input from a user, perform some actions, and then output the result in a new screen (i'm thinking as the label of the new screen). I've managed to switch between screens but i cannot figure out how to output the input from the first screen to the second screen. I've tried to make the input data a global variable so i can assign to the text of the label of the output screen, but it didn't work. Here's my python file:
from kivy.app import App
from kivy.lang import Builder
from kivy.uix.screenmanager import Screen,ScreenManager
from kivy.uix.widget import Widget
from kivy.properties import ObjectProperty
from kivy.lang import Builder
from kivy.uix.screenmanager import Screen,ScreenManager
from kivy.core.window import Window
from kivymd.app import MDApp
from kivy.uix.image import Image
from kivy.animation import Animation
from kivy.clock import Clock
from kivy.properties import ColorProperty
from kivy.uix.popup import Popup
from kivy.uix.floatlayout import FloatLayout
from plyer import filechooser
from kivymd.uix.dialog import MDDialog
Window.clearcolor = (1,1,1,1)
g_data = 'xstring'
class MainWindow(Screen):
def get_data(self):
global g_data
g_data = self.ids.user_input.text
class OutputScreen(Screen):
def ex(self):
self.ids.output_label.text = g_data
class mainApp(MDApp):
def __init__(self):
super().__init__()
def change_screen(self):
screemanager = self.root.ids['screenmanager']
screemanager.current = 'output'
def change(self):
self.change_screen()
if __name__ == '__main__':
mainApp().run()
and my kv file:
#:import utils kivy.utils
GridLayout:
cols:1
ScreenManager:
id: screenmanager
MainWindow:
id: main
name: 'main'
OutputScreen:
id: output
name: 'output'
<MainWindow>:
FloatLayout:
TextInput:
id: user_input
pos_hint:{"x" : 0.05, "top" : 0.9}
size_hint: 0.9, 0.37
Button:
pos_hint:{"top" : 0.51, "x" : 0.05}
size_hint: (None,None)
width : 150
height : 40
font_size : 23
text:'Submit'
on_release: app.change()
<OutputScreen>:
FloatLayout:
Label:
id: output_label
text: root.ex()
color: 0,0,0,1
Thank you very much.
I can't get your example to work, but you would need to do this:
g_data = '' # new global variable defined
class MainWindow(Screen):
def get_data(self):
global g_data # global goes here
g_data = self.ids.user_input.text
class OutputScreen(Screen):
def ex(self):
self.ids.output_label.text = g_data

Kivy - Adding Buttons To Screen Through Python

I am trying to make a screen view with buttons. The problem is that the amount of buttons needed each time will change, therefore I am not able to use the kv file to make theses buttons. I am having trouble adding buttons through the normal python code. Any help is appreciated.
import kivy
import webbrowser
import MSQLHandler
kivy.require('1.10.0')
from kivy.app import App
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.gridlayout import GridLayout
from kivy.uix.button import Label
from kivy.uix.widget import Widget
from kivy.uix.listview import ListItemButton
from kivy.properties import ObjectProperty
from kivy.lang import Builder
from kivy.uix.screenmanager import ScreenManager, Screen, SlideTransition, CardTransition, SwapTransition, FadeTransition, WipeTransition, FallOutTransition, RiseInTransition, NoTransition
from kivy.lang import Builder
from kivy.uix.button import Button
class Login_Failed(Screen):
def changeScreen(self, next_screen):
self.manager.current = next_screen
class Loged_In(Screen):
def changeScreen(self, next_screen):
self.manager.current = next_screen
class Registers(Screen):
def changeScreen(self, next_screen):
self.manager.current = next_screen
class Login_Screen(Screen):
teacher_connect_image = ObjectProperty()
username_text_input = ObjectProperty()
password_text_input = ObjectProperty()
teacherid_text_input = ObjectProperty()
def LoginButton(self):
if self.teacherid_text_input.text == "":
Number = 0
else:
Number = int(self.teacherid_text_input.text)
MSQLHandler.LoginSystem(self.username_text_input.text, self.password_text_input.text, Number)
def changeScreen(self, next_screen):
self.manager.current = next_screen
if MSQLHandler.LoginSystem(self.username_text_input.text, self.password_text_input.text, Number) is True:
print("Returns True")
changeScreen(self, "Loged_In")
elif MSQLHandler.LoginSystem(self.username_text_input.text, self.password_text_input.text, Number) is False:
print("Returns False")
changeScreen(self, "Login_Failed")
else:
print("Null")
class ScreenManagerr(ScreenManager):
pass
class MainKivyFrameApp(App):
def build(self):
Registers().add_widget(Button(text="Helpp"))
return ScreenManagerr()
mainFrame = MainKivyFrameApp()
mainFrame.run()
If you look to where the app is being built, you will see: Registers().add_widget(Button(text="Helpp"))
This is where I have tried to add a Button to the screen of Registers. This doesn't give me any errors, but it still does not show the button.
Solution
In the kv file, add an event (on_enter or on_pre_enter) in each screen and bind it to a callback method as shown in the following snippets and example. Remember to remove the widgets that were added dynamically before leaving the current screen, by adding an event (on_leave or on_pre_leave).
Snippets
<Registers>:
on_pre_enter: self.add_buttons(n)
on_leave: self.remove_buttons()
Example
main.py
from kivy.app import App
from kivy.uix.screenmanager import ScreenManager, Screen
from kivy.uix.button import Button
from kivy.core.window import Window
from kivy.properties import ObjectProperty, NumericProperty
class MyScreenManager(ScreenManager):
total_button = NumericProperty(2)
class Login(Screen):
login = ObjectProperty(None)
def on_pre_enter(self):
Window.size = (400, 300)
def check_password(self, instance, password):
if password == "pwd":
instance.current = "registers"
class Registers(Screen):
container = ObjectProperty(None)
def on_pre_enter(self):
Window.size = (800, 600)
def add_buttons(self, n):
print("Registers: n={}".format(n))
for i in range(n):
self.container.add_widget(Button(text="Button #{}".format(i), id=str(i)))
def remove_buttons(self, *args):
for child in [child for child in self.container.children]:
self.container.remove_widget(child)
class Welcome(Screen):
pass
class TestApp(App):
title = "ScreenManager - Add Widgets Dynamically"
def build(self):
return MyScreenManager()
if __name__ == "__main__":
TestApp().run()
test.kv
#:kivy 1.10.0
#:import SwapTransition kivy.uix.screenmanager.SwapTransition
<MyScreenManager>:
transition: SwapTransition()
Login:
Registers:
on_pre_enter:
self.add_buttons(app.root.total_button)
on_leave:
self.remove_buttons()
Welcome:
<Login>:
id: login
name: "login"
login: login
GridLayout:
size_hint: (0.5, 0.5)
pos_hint: {"center_x": 0.5, "center_y": 0.6}
rows: 3
padding: 20
Label:
size_hint: (0.2, 0.2)
text:"Password:"
font_size: 30
halign: "center"
valign: "middle"
TextInput:
id: password
size_hint: (0.2, 0.06)
cursor_blink: True
font_size: 20
multiline: False
password: True
Button:
text: "Continue"
size_hint: (0.2, 0.08)
on_release:
root.login.check_password(root.manager, password.text)
<Registers>:
name:'registers'
container: container
BoxLayout:
orientation: 'vertical'
Button:
text: 'Return to Login'
on_press: root.manager.current = 'login'
Button:
text: 'Next Screen'
on_press: root.manager.current = 'welcome'
BoxLayout:
id: container
orientation: 'vertical'
<Welcome>:
name:'welcome'
BoxLayout:
Label:
text: 'Welcome!'
Button:
text: 'Return to Registers'
on_press:
app.root.total_button = 5
root.manager.current = 'registers'
Output

Kivy change label text with python

I'm semi-OK with Python but brand new to Kivy, I know my problem is referencing the label ID but I can't seem to solve it and searching doesn't seem to give me what I need.
I'm trying to get a label to display the current time, so I know I have the right framework in terms of updating etc but I'm sure its all down to referencing the label ID somehow and its that I'm struggling with?
The following code runs fine, displays the labels etc until I try to update the label_text.text at which point i get an error: AttributeError: 'float' object has no attribute 'lbl_time'. I've tried str(time.strftime("%H:%M:%S")) but that doesn't solve it.
from kivy.app import App
from kivy.base import runTouchApp
from kivy.lang import Builder
from kivy.properties import ListProperty
from kivy.uix.boxlayout import BoxLayout
from kivy.properties import ObjectProperty
from kivy.uix.screenmanager import ScreenManager, Screen, WipeTransition, FadeTransition
from kivy.uix.anchorlayout import AnchorLayout
from kivy.properties import ObjectProperty, StringProperty
from kivy.clock import Clock
import time
from datetime import datetime
class MainScreen(Screen):
def update_time(self):
lbl_time = ObjectProperty()
MyTime = time.strftime("%H:%M:%S")
self.lbl_time.text = MyTime
class DetailScreen(Screen):
pass
class SettingsScreen(Screen):
pass
class MyScreenManager(ScreenManager):
pass
root_widget = Builder.load_string('''
MyScreenManager:
MainScreen:
DetailScreen:
SettingsScreen:
<MainScreen>:
name: 'main'
BoxLayout:
orientation: 'vertical'
Label:
id: lbl_time
text: 'Time'
font_size: 60
Label:
text: 'Main2'
font_size: 30
GridLayout:
cols: 2
Label:
text: 'Bottom'
font_size: 30
Label:
text: 'Bottom1'
font_size: 30
<DetailScreen>:
name: 'details'
<SettingsScreen>:
name: 'settings'
''')
class ScreenManagerApp(App):
def build(self):
return root_widget
def on_start(self):
Clock.schedule_interval(MainScreen.update_time, 1)
ScreenManagerApp().run()
This was more of a Python problem rather than a Kivy one. You were calling the update_time of the class MainScreen class, not of the object/instance of the MainScreen. Basically, you would need to save a reference to the object (self.main_screen) in the build method, and then use it in the on_start.
class ScreenManagerApp(App):
def build(self):
self.main_screen = MainScreen()
return self.main_screen
def on_start(self):
Clock.schedule_interval(self.main_screen.update_time, 1)
Also you cannot access id outside of the kv language, i.e. in the python. You have to reference the id by adding a property, e.g. the_time:
<MainScreen>:
name: 'main'
the_time: _id_lbl_time
BoxLayout:
orientation: 'vertical'
Label:
id: _id_lbl_time
A minor problem is that the update_time() receives to parameters. Also, there were quite a few weird things in your code, so I couldn't run the code. I fixed all the above in the code below:
from kivy.app import App
from kivy.lang import Builder
from kivy.uix.screenmanager import Screen
from kivy.properties import ObjectProperty, StringProperty
from kivy.clock import Clock
import time
from datetime import datetime
Builder.load_string('''
<MainScreen>:
name: 'main'
the_time: _id_lbl_time
BoxLayout:
orientation: 'vertical'
Label:
id: _id_lbl_time
text: 'Time'
font_size: 60
''')
class MainScreen(Screen):
def update_time(self, sec):
MyTime = time.strftime("%H:%M:%S")
self.the_time.text = MyTime
class ScreenManagerApp(App):
def build(self):
self.main_screen = MainScreen()
return self.main_screen
def on_start(self):
Clock.schedule_interval(self.main_screen.update_time, 1)
ScreenManagerApp().run()

Categories

Resources