python kivy screen confog - python

main.py file
from kivymd.app import MDApp
from kivy.lang import Builder
class Hero(MDApp):
def build(self):
return Builder.load_file("stackoverflow.kv")
Hero().run()
the above is the main.py file
please guys help me with this
stackoverflow.kv file
ScreenManager:
id: screenmanager
Screen:
id: accountscreen
name: "screen1"
BoxLayout:
oreintation: "vertical"
MDGridLayout:
cols:1## Heading ##
MDLabel:
text: "[color=00FF00]Sign In[/color]"
bold:True
markup:True
halign: "center"
valign: "middle"
MDTextField:
id: username
padding: "30dp"
spacing: "30dp"
hint_text:"User Name or Email"
pos_hint: {"center_x":.5,"center_y":.5}
MDTextField:
id:password
padding: "20dp"
spacing: "20dp"
hint_text:"Password"
MDRectangleFlatButton:
text:"Sign In"
padding: "16dp"
spacing: "16dp"
halign: "center"
pos_hint: {"center_x":.9,"center_y":.5}
on_press: app.root.current="screen2"
BoxLayout:
oreintation: "vertical"
Screen:
id: welcome_screen
name: "screen2"
MDLabel:
text: "welcome"
valign: "middle"
halign: "center"
any time i open the app i get the sign in screen how can i save the user information and clear the screen using config ini file please help me????

Here is a version of you code that uses Config to do what you want:
import os
from kivymd.app import MDApp
from kivy.lang import Builder
class Hero(MDApp):
def build(self):
sm = Builder.load_file("stackoverflow.kv")
self.load_my_config()
sm.current = self.initial_screen
return sm
def build_config(self, config):
# Make sure that the config has at least default entries that we need
config.setdefaults('app', {
'startup_screen': 'screen1',
})
def get_application_config(self):
# This defines the path and name where the ini file is located
return str(os.path.join(os.path.expanduser('~'), 'Hero.ini'))
def on_stop(self):
# save the config when the app exits
self.save_config()
def save_config(self):
# this writes the data we want to save to the config
# set the data in the config
self.config.set('app', 'startup_screen', 'screen2')
# write the config file
self.config.write()
def load_my_config(self):
# extract our saved data from the config (it has already been read)
self.initial_screen = self.config.get('app', 'startup_screen', fallback='screen1')
Hero().run()
And in the kv file, I would add a call to save the configuration when the Sign In button is pressed:
MDRectangleFlatButton:
text:"Sign In"
padding: "16dp"
spacing: "16dp"
halign: "center"
pos_hint: {"center_x":.9,"center_y":.5}
on_press:
app.root.current="screen2"
app.save_config()

Related

Why my ScreenManager not switching in Kivy

I'm trying to build an interface in python with Kivy. To do this, i want to follow this structure:
[ScreenManager#1] -> [Login Screen]
[ScreenManager#2] -> [All others screens]
My ScreenManager#1 is declared in my App function in python file. My ScreenManager#2 is initialised in a kv file. To simply the help that you can bring to me, i've joined the two in the code below.
my AllScreensScreenManager#2, need to have a template shared with all the other screens. I've gave an id to it and call this one with my button in my LoginScreen, like this was suggested here. But the switch is not working. What i'm doing wrong with it.
import kivy
kivy.require('2.1.0') # replace with your current kivy version !
from kivy.app import App
from kivy.lang import Builder
from kivy.uix.screenmanager import ScreenManager,Screen
Builder.load_string('''
<AllScreens>:
id: second_manager
manager: scr_manager
orientation: "vertical"
BoxLayout:
ScreenManager:
id: scr_manager
transition: "left"
Welcome:
GenerateScreen:
ModifyScreen:
ConsultScreen:
LogoutScreen:
BoxLayout:
size_hint: 1, None
height: "40dp"
pos_hint: {"bottom": 0}
spacing: "5dp"
Button:
id: consult
text: "Consult"
on_press: root.manager.current("consult")
Button:
id: modify
text: "Modify"
on_press: root.manager.current("modify")
Button:
id: generate
text: "Generate"
on_press: root.manager.current("generate")
Button:
id: logout
text: "Logout"
on_press: root.manager.current("logout")
<LoginScreen>:
name: "login"
BoxLayout:
Label:
text: "Login"
Button:
text: "Connect"
on_release: second_manager.current("welcome")
<WelcomeScreen>:
name: "welcome"
BoxLayout:
Label:
text: "welcome"
<ConsultScreen>:
name: "consult"
BoxLayout:
Label:
text: "consult"
<GenerateScreen>:
name: "generate"
BoxLayout:
Label:
text: "password"
''')
class ScreenManagement(ScreenManager):
pass
class LoginScreen(Screen):
print("login screen")
pass
class WelcomeScreen(Screen):
pass
class AllScreens(ScreenManager):
pass
class ConsultScreen(Screen):
pass
class GenerateScreen(Screen):
pass
class MyApp(App):
def build(self):
sm = ScreenManagement()
sm.add_widget(LoginScreen(name="login"))
return sm
if __name__ == '__main__':
MyApp().run()

Add widget dynamically from outside class (error)

I´m learning kivy, and it has passed 3 weeks since i face this problem without encounter a solution, so i hope any of u guys could help me, i would appreciate it.
I have a main file:
from app import MyProgramApp
if __name__ == "__main__":
winapp = MyProgramApp()
winapp.run()
from where i start my app. Then i have a directory called "app", inside there is the following "init.py" file.
from kivy.app import App
from kivy.utils import QueryDict, rgba
from kivy.core.window import Window
from .view import MainWindow
Window.minimum_width = 500
Window.minimum_height = 650
Window.maximize()
class MyProgramApp(App):
colors = QueryDict()
colors.primary = rgba('#2D9CDB')
colors.secondary = rgba('#16213E')
colors.succes = rgba('#1FC98E')
colors.warning = rgba('#F2C94C')
colors.danger = rgba('#E85757')
colors.grey_dark = rgba('#C4C4C4')
colors.grey_light = rgba('#F5F5F5')
colors.black = rgba('#A1A1A1')
colors.white = rgba('#FFFFFF')
def build(self):
return MainWindow()
Same folder app, i have the following "view.py".
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.behaviors import ToggleButtonBehavior
from kivy.properties import StringProperty
from kivy.uix.screenmanager import ScreenManager
class MainWindow(BoxLayout):
username = StringProperty("Usuario")
def __init__(self, **kw):
super().__init__(**kw)
def on_press_home(self):
self.ids.scrn_mngr.current = "scrn_home"
class ViewManager(ScreenManager):
def __init__(self, **kw):
super().__init__(**kw)
class NavTab(ToggleButtonBehavior, BoxLayout):
text = StringProperty('')
icon = StringProperty('')
def __init__(self, **kw):
super().__init__(**kw)
and finally for that folder i have "myprogram.kv"
#:kivy 2.1.0
#:import Home views.home.Home
<MainWindow>:
spacing: dp(8)
canvas.before:
Color:
rgba: app.colors.white
Rectangle:
pos: self.pos
size: self.size
# NAVIGATION BAR
BoxLayout:
id: nav_menu
size_hint_x: .2
orientation: "vertical"
size_hint_min_x: dp(100)
# LOGO
BoxLayout:
id: logo_nbox
size_hint_y: .1
size_hint_min_y: dp(70)
padding: dp(16)
AnchorLayout:
anchor_x: "right"
size_hint_x: None
width: dp(52)
halign: "left"
Label:
text: "COMPANY"
halign: "center"
BoxLayout:
orientation: "vertical"
Label:
text: "COMPANY"
halign: "center"
Label:
text: "Phrase"
halign: "center"
# OPTIONS
GridLayout:
id: tabs_box
cols: 1
spacing: dp(4)
size_hint_y: .5
canvas.before:
Color:
rgba: app.colors.grey_dark
Rectangle:
pos: self.pos
size: [self.size[0], dp(1)]
NavTab:
text: "Home"
state: "down"
on_press: root.on_press_home()
# BODY
BoxLayout:
size_hint_x: .8
spacing: dp(8)
orientation: "vertical"
padding: [dp(16), dp(8), dp(12), dp(8)]
canvas.before:
Color:
rgba: app.colors.grey_light
Rectangle:
pos: self.pos
size: self.size
# SCREENS
BoxLayout:
ViewManager:
id: scrn_mngr
<ViewManager>:
Screen:
name: "scrn_home"
Home:
id: home
<NavTab>:
background_normal: ""
background_down: ""
background_color: [0,0,0,0]
group: "tabs"
size_hint_y: None
height: dp(45)
spacing: dp(4)
canvas.before:
Color:
rgba: [0,0,0,0] if self.state == "normal" else rgba("#E1F1FF")
Rectangle:
pos: self.pos
size: self.size
Color:
rgba: [0,0,0,0] if self.state == "normal" else app.colors.primary
Rectangle:
pos: [self.pos[0]+self.size[0]-dp(1), self.pos[1]]
size: [dp(8), self.size[1]]
Label:
halign: "left"
valign: "middle"
text: root.text
color: app.colors.grey_dark if root.state == "normal" else app.colors.primary
Then i got another folder called "views" inside i have another folder called "home", inside home we encounter 3 files "init.py", "home.kv", "home.py". the first one "init.py" is the following.
from .home import Home
then we got "home.kv".
#:kivy 2.1.0
<Home>:
orientation: "vertical"
Label:
size_hint_y: .1
text: "Other"
Button:
size_hint_y: .1
text: "popup"
on_press: root.open_popup()
BoxLayout:
size_hint_y: .8
id: home_box
<SomePopup>:
title: "SOME TITLE"
title_align: "center"
title_color: app.colors.primary
size_hint: .25, .8
size_hint_min_x: dp(200)
pos_hint: {"x": .1, "top": .9}
BoxLayout:
orientation: "vertical"
padding: [dp(0), dp(12), dp(0), dp(12)]
Label:
text: "Some text"
Button:
text: "create buttons on box"
on_press: root.modify_home_box()
and finally and the problem that i´m facing is whit the following file "home.py"
from kivy.lang import Builder
from kivy.uix.boxlayout import BoxLayout
from kivy.factory import Factory
from kivy.uix.popup import Popup
from kivy.uix.button import Button
from kivy.app import App
Builder.load_file('views/home/home.kv')
class Home(BoxLayout):
def __init__(self, **kwargs):
super().__init__(**kwargs)
def open_popup(self):
Factory.SomePopup().open()
class SomePopup(Popup):
def __init__(self, **kw):
super().__init__(**kw)
def modify_home_box(self):
my_app = App.get_running_app().root
my_box = my_app.ids.home.ids.home_box
custom_button = Button(
text = "something"
)
my_box.add_widget(custom_button)
That i´m trying to do is actually modify "home_box" with is store on ids Home dictionary, i also try with ObjectProperty (but that gives and Attribute Error, since i only could read propertys but doesnt modify it), instance of a new Home class doesnt work... searching for current app in App appear doesnt work since Home is store i think on screenManager...
I need add a button or some widget to "home_box" from outside class "SomePopup". I also drop here a repository on github with the whole code. github_repo
I don't know how to solve my issue, and i try with the resources available here on stack as well other net places... any help would be appreciate.
Just a very complicated path to the widget of interest. In your modify_home_box() method, try replacing:
my_app = App.get_running_app().root
my_box = my_app.ids.home.ids.home_box
with:
my_app = App.get_running_app().root
my_box = my_app.ids.scrn_mngr.ids.home.ids.home_box

How do I pass an argument between KivyMD screens?

When going from the first screen to the second screen, I want to pass a variable as an argument so that kivyMD can update the second screen from text stored in an excel file. The following is a skeleton of my app's functionality:
The user reaches Screen 1 thru the navigation drawer in KivyMD, screen 1 presents the user with two options on two small clickable MDCards:
"Change text to 1"
"Change text to 2"
After clicking on one of these, the app switches to screen 2 with a single big MDCard, the text on this MDCard should change to reflect the option the user chose.
However, kivy is pulling the text that is to be displayed on the big MDCard from an excel file.
The variable that I want to pass from screen 1 to screen 2 is simply a number (1 or 2) that will tell kivy which row in the excel file it should pull the text from
If the user clicks "Change text to 1" then the first screen should pass "1" as the argument row_x to the function def change_text() (see screen 2 .py) so that the text in row 1 of excel can be displayed on the second screen. How can I achieve this?
I have 4 files in total; 3 are .py files (one for the main app, one for screen 1, and one for screen 2), and the excel file
NOTE: in the code below, Screen 1 & 2 are called Element 1 & 2 respectfully
Main.py:
from kivy.lang import Builder
from kivy.uix.boxlayout import BoxLayout
from kivy.properties import ObjectProperty
from kivymd.app import MDApp
from element_1 import element_1_screen
from element_2 import element_2_screen
MainNavigation = '''
<ContentNavigationDrawer>:
ScrollView:
MDList:
OneLineListItem:
text: 'Go to Element 1'
on_press:
root.nav_drawer.set_state("close")
root.screen_manager.current = "go_to_element_1_screen"
Screen:
MDToolbar:
id: toolbar
pos_hint: {"top": 1}
elevation: 10
left_action_items: [["menu", lambda x: nav_drawer.set_state("open")]]
MDNavigationLayout:
x: toolbar.height
ScreenManager:
id: screen_manager
Screen:
name: "words_nav_item"
element_1_screen:
name: "go_to_element_1_screen"
element_2_screen:
name: "go_to_element_2_screen"
MDNavigationDrawer:
id: nav_drawer
ContentNavigationDrawer:
screen_manager: screen_manager
nav_drawer: nav_drawer
'''
class ContentNavigationDrawer(BoxLayout):
screen_manager = ObjectProperty()
nav_drawer = ObjectProperty()
class mainApp(MDApp):
def build(self):
self.theme_cls.primary_palette = "Red"
return Builder.load_string(MainNavigation)
mainApp().run()
Screen 1 / Element 1
from kivy.lang import Builder
from kivymd.uix.screen import MDScreen
element_1_contents = '''
<element_1_screen>:
MDGridLayout:
rows: 2
size: root.width, root.height
pos_hint: {"center_x": .8, "center_y": .2}
spacing: 40
MDCard:
orientation: 'vertical'
size_hint: None, None
size: "360dp", "120dp"
ripple_behavior: True
on_release:
root.manager.current = "go_to_element_2_screen"
MDLabel:
id: LabelTextID
text: "Change Text to 1"
halign: 'center'
MDCard:
orientation: 'vertical'
size_hint: None, None
size: "360dp", "120dp"
ripple_behavior: True
on_release:
root.manager.current = "go_to_element_2_screen"
MDLabel:
id: LabelTextID
text: "Change Text to 2"
halign: 'center'
'''
class element_1_screen(MDScreen):
def __init__(self, **kwargs):
super().__init__(**kwargs)
Builder.load_string(element_1_contents)
Screen 2 / Element 2
from kivy.lang import Builder
from kivymd.uix.screen import MDScreen
import openpyxl
element_2_contents = '''
<element_2_screen>:
MDCard:
orientation: 'vertical'
size_hint: None, None
size: "360dp", "360dp"
pos_hint: {"center_x": .5, "center_y": .5}
ripple_behavior: True
focus_behavior: True
on_release: root.manager.current = "go_to_element_1_screen"
MDLabel:
id: TextID
text: "NOTHING HAS CHANGED"
halign: 'center'
MDLabel:
text: "(Click here to return)"
halign: 'center'
'''
class element_2_screen(MDScreen):
def __init__(self, **kwargs):
super().__init__(**kwargs)
path = "data.xlsx"
self.wb_obj = openpyxl.load_workbook(path)
self.sheet_obj = self.wb_obj.active
Builder.load_string(element_2_contents)
def change_text(self, row_x=0):
row_number = self.sheet_obj.cell(row_x, column=1)
self.ids.TextID.text = str(row_number.value)
And the excel file only has two entries in Column A:
Row 1: You have chosen 1
Row 2: You have chosen 2
I found the answer and now it works flawlessly. Someone over on Reddit (u/Username_RANDINT) helped me, this is what they said:
The ScreenManager has a get_screen() method. You could use it to get
the instance of the second screen and call the change_text() method on
that. In the same place where you switch screens, add another line:
on_release:
root.manager.current = "go_to_element_2_screen"
root.manager.get_screen("go_to_element_2_screen").change_text(1)
Then the same for the other card, just pass in 2 instead of 1.

kivymd text field stills shows the hint_text in the field after typing

I am having trouble with MDTextField. It carries on displaying the hint inside the textfield while typing. I have tried setting the background color to hide it but that didn't work. I have looked at a few tutorials and everyone seems to be doing it the same way as me and it just works for other people so i feel i have done something really wrong.
Image of what happens this is my first post so i am not aloud to post images :)
Any help will be greatly appreciated. Thanks in advance.
main.py
from kivy.app import App
from kivy.uix.button import Button
from kivy.uix.floatlayout import FloatLayout
from kivy.core.window import Windowfrom kivy.config import Config
from kivy.uix.screenmanager import ScreenManager, Screen
from kivymd.theming import ThemeManager
from kivy.lang import Builder
from kivymd.app import MDApp
from kivy.graphics import Rectangle, Color
import pymysql
class WelcomeScreen(Screen):
pass
class LoginScreen(Screen):
pass
class RegisterScreen(Screen):
pass
class WindowManager(ScreenManager):
pass
class MainApp(MDApp):
def build(self):
# theme_cls = ThemeManager()
return Builder.load_file("main.kv")
def change_screen(self, screen, direction):
self.root.transition.direction = direction
self.root.current = screen
if __name__ == "__main__":
MainApp().run()
main.kv
#: import Window kivy.core.window.Window
#: import MDLabel kivymd.uix.label.MDLabel
#: import Rectangle kivy.graphics.Rectangle
#: import Color kivy.graphics.Rectangle
WindowManager:
WelcomeScreen:
LoginScreen:
RegisterScreen:
<WelcomeScreen>:
name: "welcome_screen"
FloatLayout:
orientation: "vertical"
MDToolbar:
id: toolbar
title: "SecureIT 24/7"
pos_hint: {'top': 1}
Button:
text: 'Login'
color: 1, 1, 1, 1
size_hint: 0.25, 0.25
pos_hint: {"right":0.625, "top":0.80}
on_release:
app.root.current = "login_screen"
Button:
text: 'Register'
color: 1,1,1,1
size_hint: 0.25, 0.25
pos_hint: {"right":0.625, "top":0.55 }
on_release:
app.root.current = "register_screen"
<LoginScreen>:
name: "login_screen"
FloatLayout:
MDBanner:
id: banner
text: "Login"
# The widget that is under the banner.
# It will be shifted down to the height of the banner.
MDToolbar:
id: toolbar
title: "Login"
elevation: 10
pos_hint: {'top': 1}
left_action_items: [['arrow-left', lambda screen: app.change_screen('welcome_screen', 'right')]]
FloatLayout:
padding: [50,50,50,50]
spacing: 50
FloatLayout:
orientation: 'vertical'
Label:
text: 'Login'
font_size: 18
halign: 'center'
text_size: root.width-20, 20
color: 0,0,0,1
pos_hint: {"right":1, "top":1.25}
TextInput:
id: login
multiline:False
font_size: 28
size_hint: 0.50, 0.10
pos_hint: {"right":0.75, "top":0.70}
FloatLayout:
orientation: 'vertical'
Label:
text: 'Password'
halign: 'center'
font_size: 18
text_size: root.width-20, 20
color: 0,0,0,1
TextInput:
id: password
multiline:False
password:True
font_size: 28
size_hint: 0.50, 0.10
pos_hint: {"right":0.75, "top":0.45}
Button:
text: 'Login'
size_hint: 0.25, 0.25
font_size: 24
pos_hint: {"right":0.625, "top":0.30}
<WhiteLabel#MDLabel>
height: self.texture_size[1]
theme_text_color: "Custom"
text_color: 1, 1, 1, 1
<CustomInput#MDTextField>
multiline:False
# required: True
mode: "line"
pos_hint: {"right": 0.456}
current_hint_text_color: [0,0,0,0.5]
<RegisterScreen>:
name: "register_screen"
FloatLayout:
MDBanner:
id: banner
text: "ioshrdioaoisdhf"
MDToolbar:
id: toolbar
title: "Register"
elevation: 10
pos_hint: {'top': 1}
left_action_items: [['arrow-left', lambda screen: app.change_screen('welcome_screen', 'right')]]
BoxLayout:
orientation: "vertical"
height: self.minimum_height * 2
size_hint_y: None
pos_hint: {"top": 2}
CustomInput:
id: firstname
hint_text: "color_mode = 'custom'"
CustomInput:
id: surname
hint_text: 'Surname'
CustomInput:
id: email
hint_text: 'Email'
By naming your kv file as main.kv, you are taking advantage of the automatic loading of correctly named kv files as described in the documentation. However, you are also loading the same file using Builder.load_file("main.kv"). Loading the same kv file more than once can cause the sort of problems you are seeing. You can fix your problem by simply eliminating the call to Builder.load_file("main.kv"), or removing the entire build() method, or by changing the name of either the kv file or the MainApp class.

Python kivy link checkbox from application to .kv

I am a new user to kivy.
I need to link a checkbox from the .kv interface so that it have an impact on the underlying python application.
I tried the following code for my application:
from kivy.app import App
from kivy.uix.floatlayout import FloatLayout
from kivy.factory import Factory
from kivy.properties import ObjectProperty
from kivy.uix.popup import Popup
from kivy.uix.checkbox import CheckBox
import os
class LoadDialog(FloatLayout):
load = ObjectProperty(None)
cancel = ObjectProperty(None)
class Root(FloatLayout):
loadfile = ObjectProperty(None)
checkbox = CheckBox()
def dismiss_popup(self):
self._popup.dismiss()
def show_load(self):
content = LoadDialog(load=self.load, cancel=self.dismiss_popup)
self._popup = Popup(title="Load file", content=content, size_hint=(0.9, 0.9))
self._popup.open()
def load(self, path, filename):
print 'user chose: %s' % os.path.join(path, filename[0])
print self.checkbox.active
self.dismiss_popup()
def activate_checkbox(self):
print 'activate checkbox'
self.checkbox._toggle_active()
class Chooser(App):
pass
Factory.register('Root', cls=Root)
Factory.register('LoadDialog', cls=LoadDialog)
if __name__ == '__main__':
Chooser().run()
with the following chooser.kv file:
#:kivy 1.1.0
Root:
BoxLayout:
orientation: 'vertical'
BoxLayout:
size_hint_y: 90
height: 30
Button:
text: 'Load'
on_release: root.show_load()
BoxLayout:
size_hint_y: 90
height: 30
CheckBox:
center: self.parent.center
on_active: root.activate_checkbox
Label:
font_size: 20
center_x: self.parent.width / 4
top: self.parent.top - 50
text: 'Faster'
<LoadDialog>:
BoxLayout:
size: root.size
pos: root.pos
orientation: "vertical"
FileChooserListView:
id: filechooser
BoxLayout:
size_hint_y: None
height: 30
Button:
text: "Cancel"
on_release: root.cancel()
Button:
text: "Load"
on_release: root.load(filechooser.path, filechooser.selection)
Unfortunately it was to no avail: it seems that the state of the CheckBox user interface element have no effect whatsoever on the state of the checkbox inside the Root Class.
Is there any simple way to link the two?
on_active: root.activate_checkbox
This doesn't do anything, you want root.activate_checkbox().

Categories

Resources