I create a simple app with Python and KivyMD. When the app running, the login screen asks for input. It was something like this:
from kivy.app import App
from kivymd.app import MDApp
from kivy.lang import Builder
from kivy.core.window import Window
from kivy.properties import StringProperty
from kivy.uix.screenmanager import ScreenManager,Screen
class Login(Screen):
def __init__(self, *args, **kwargs):
super(login,self).__init__(*args,**kwargs)
self.user=""
self.username=self.ids.usernamebox.text
self.password=self.ids.passwordbox.text
def checkusername(self)
if self.username=="something" and self.password=="something":
self.user="admin"
else:
self.user="member"
sm.current='nextscreen'
class NextScreen(Screen):
def somefeatures(self):
if Login.user="admin":
print(Login.user)
pass
if Login.user="member":
print(Login.user)
pass
class MyApp(MDApp):
def build(self):
global sm
sm=ScreenManager()
sm.add_widget(Logon(name='login'))
sm.add_widget(NextScreen(name='nextscreen'))
also, the kivy code if it any helps:
<Login>
MDBoxLayout:
orientation: "vertical"
MDTextField:
id: usernamebox
hint_text: "Username"
MDTextField:
id: passwordbox
hint_text: "Password"
MDFillRoundFlatButton:
id: login
text: "Login"
on_release: root.checkusername()
pos_hint: {"center_x":.5}
<NextScreen>
MDBoxLayout:
orientation: "vertical"
MDFlatButton:
text: "test"
on_press: root.somefeatures()
I'm using kivy screen manager to switch between the classes.
What I try to achieve is how to make somefeatures prints the correct value of user after the user logged in
So far I've tried:
initializing the login class l=login() and access with l.user, didn't work because __init__ returns 'user' as empty string
create global user, but still empty string
create setuser and getuser method within class login, but still can't return the value
initializing user outside the class user="" before any other classes, also empty string
Accessing the value of login class like the code above, it says type object Login has no attribute user
Is there is a way to achieve this? I want the value of user is still remembered as long as the app running (or until I make logout button, idk)
Thank you so much.
this is main.py
from kivy.uix.button import Button
from kivy.uix.textinput import TextInput
from kivy.uix.screenmanager import ScreenManager, Screen
from kivy.lang import Builder
from kivy.app import App
from kivy.uix.widget import Widget
from kivy.properties import StringProperty, ObjectProperty, NumericProperty, ReferenceListProperty
Builder.load_file('the.kv')
class fscreen(Widget):
def __init__(self,**kwargs):
super().__init__(**kwargs)
theapp.user = ''
def checkusername(self):
self.username = self.ids.password.text
self.password = self.ids.username.text
if self.username == "something" and self.password == "something":
theapp.user = "admin"
else:
theapp.user = "member"
print(self.username, self.password, theapp.user)
theapp.screenm.current = "second screen"
theapp.secscreen.userlabel = 'welcome ' + theapp.user
class secscreen(Widget):
userlabel = StringProperty()
def __init__(self,**kwargs):
super().__init__(**kwargs)
self.userlabel = ''
class thscreen(Widget):
def __init__(self, **kwargs):
supper().__init__(**kwargs)
pass
class theapp(App):
def build(self):
self.screenm = ScreenManager()
self.fscreen = fscreen()
screen = Screen(name = "first screen")
screen.add_widget(self.fscreen)
self.screenm.add_widget(screen)
self.secscreen = secscreen()
screen = Screen(name = "second screen")
screen.add_widget(self.secscreen)
self.screenm.add_widget(screen)
return self.screenm
if __name__ == "__main__":
theapp = theapp()
theapp.run()
the.kv file
<fscreen>
TextInput:
size: root.width*0.2, root.height*0.1
pos: root.width*0.45, root.height*0.5
id: username
hint_text: 'username'
TextInput:
size: root.width*0.2, root.height*0.1
pos: root.width*0.45, root.height*0.4
id: password
hint_text: 'password'
Button:
size: root.width*0.2, root.height*0.1
pos: root.width*0.45, root.height*0.1
text: 'login or something'
on_press: root.checkusername()
<secscreen>
Label:
text: root.userlabel
size: root.width*0.2, root.height*0.1
pos: root.width*0.45, root.height*0.4
ur problem was a class related, u should read more about python classes.
Related
I have three codes, I am confused with how I would navigate to the next screen in my Organize.kv from my login.py, I have the main kv file that has all the screens saved and the login python and kv file that manages the login screen, the login kv file balances two different tabs, so far I have the create tab that sends you to the create class of the login python file which is connected to mysql, how would I switch screens to the Main Menu which is in the main Organize.kv file from the login python file? Sorry if this doesn't make sense, I'm super warn out from trying to figure this out.
Anything helps, thank you
The main Organize.kv that has all the screens
#:import organize organize
#:import navigation_screen_manager navigation_screen_manager
#:import anchorlayout_with_action_bar anchorlayout_with_action_bar
#:import sharpen_skills sharpen_skills
#:import login login
<MainMenu#BoxLayout>:
orientation: "vertical"
padding: "40dp"
spacing: "20dp"
size_hint: .7, .9
pos_hint: {"center_x": .5}
Button:
text: "Organize"
on_press: app.manager.push("screen2")
Button:
text: "Journal"
on_press: app.manager.push("screen3")
Button:
text: "Sharpen Skills"
on_press: app.manager.push("SkillsExamplesTabs")
Button:
text: "Exit"
on_press: app.stop()
<MyScreenManager>:
Screen:
name: "Login"
title: "login"
LoginTabs:
Screen:
name: "MainMenu"
MainMenu:
Screen:
name: "screen2"
AnchorLayoutWithActionBar:
title: "Organize"
Screen:
name: "screen3"
AnchorLayoutWithActionBar:
title: "Journal"
Screen:
name: "SkillsExamplesTabs"
AnchorLayoutWithActionBar:
title: "Sharpen Skills"
SkillsExamplesTabs:
My login.kv file
<LoginTabs#TabbedPanel>:
do_default_tab: False
TabbedPanelItem:
text: "Create Account"
Create:
TabbedPanelItem:
text: "Login"
Login:
and finally my login.py file
from kivy.lang import Builder
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.screenmanager import ScreenManager
from kivy.uix.stacklayout import StackLayout
from kivy.uix.anchorlayout import AnchorLayout
from kivy.uix.widget import Widget
from kivy.uix.button import Button
from kivy.uix.label import Label
from kivy.uix.textinput import TextInput
from kivy.uix.label import Label
from kivy.graphics import Color, Rectangle
import mysql.connector
import navigation_screen_manager
from kivy.uix.screenmanager import ScreenManager, Screen
from navigation_screen_manager import NavigationScreenManager
Builder.load_file("login.kv")
Builder.load_file("Organize.kv")
sm = ScreenManager()
class MyScreenManager(NavigationScreenManager):
pass
class Create(BoxLayout):
def __init__(self, **kwargs):
super().__init__(**kwargs)
self.orientation = "vertical"
self.build()
def build(self):
self.warning = Label(text="", pos_hint={'center_x': .5, 'center_y': .5})
user_label = Label(text="Username", size_hint=(.5, .5),
pos_hint={'center_x': .5, 'center_y': .5})
self.user_textinput = TextInput(text='Enter Username')
pas_label = Label(text="Password", size_hint=(.5, .5),
pos_hint={'center_x': .5, 'center_y': .5})
self.pas_textinput = TextInput(text="enter Password")
enter_button = Button(text="Create")
with user_label.canvas:
Color(0, .25, 1, .25)
enter_button.bind(on_press=self.Add)
self.add_widget(self.warning)
self.add_widget(user_label)
self.add_widget(self.user_textinput)
self.add_widget(pas_label)
self.add_widget(self.pas_textinput)
self.add_widget(enter_button)
def Add(self, btn):
print("Working")
t1 = self.user_textinput.text
t2 = self.pas_textinput.text
print(f"T1 = {t1} and {t2}")
conn = mysql.connector.connect(
user='root',
password='*******',
host='127.0.0.1',
database='Usersdb')
mycursor = conn.cursor()
try:
sql = "INSERT INTO user_info (user_name, user_pass) VALUES (%s, %s)"
val = (t1,t2)
mycursor.execute(sql,val)
conn.commit()
except:
self.warning = "Username Already Taken"
class Login(StackLayout):
pass
And finally my App class
from kivy.app import App
from kivy.uix.label import Label
from kivy.metrics import dp
from kivy.properties import StringProperty, BooleanProperty, ObjectProperty
from kivy.uix.anchorlayout import AnchorLayout
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.button import Button
from kivy.uix.gridlayout import GridLayout
from kivy.uix.popup import Popup
from kivy.uix.floatlayout import FloatLayout
from kivy.uix.stacklayout import StackLayout
from kivy.uix.widget import Widget
from navigation_screen_manager import NavigationScreenManager
class MyScreenManager(NavigationScreenManager):
pass
class Organizer(App):
manager = ObjectProperty(None)
def build(self):
self.manager = MyScreenManager()
return self.manager
Organizer().run()
And my Navigation Screen Manager
from kivy.uix.screenmanager import ScreenManager
class NavigationScreenManager(ScreenManager):
screen_stack = []
def push(self, screen_name):
self.screen_stack.append(self.current)
self.transition.direction = "left"
self.current = screen_name
def pop(self):
if len(self.screen_stack) > 0:
screen_name = self.screen_stack[-1]
del self.screen_stack[-1]
self.transition.direction = "right"
self.current = screen_name
Good day. You must access your screen manager in order to set the current screen which is your active screen. In your App class, I recommend saving your screen manager as an attribute via the on_start function.
class MyApp(App):
def on_start(self):
screen_manager = self.root
From there, you could set your current screen using callback methods in kivy or python.
#in kv
on_release: setattr(app.screen_manager, 'current', 'the next screen name')
#in python
def set_screen_callback(self, instance *args):
app.screen_manager.current = "the next screen name"
Your post does not include your App class, so a specific answer is impossible. The fact that you have multiple kv files is irrelevant once those kv files are loaded. In general, you just set the current property of the ScreenManager to the name of the Screen that you want displayed.
Again, the fact that you have multiple kv files is irrelevant once those kv files are loaded. So in any of the kv files, I believe that you should be able to use:
app.manager.push("MainMenu")
or:
app.manager.current = "MainMenu"
to get to the MainMenu Screen.
I've got a toggle button that I'm using to start and stop a process. When the process is being stopped, I have a popup box that comes up, asking the user to enter a password to confirm they want to end the process.
Only once the correct password is provided do I want the state of the toggle button to change from "down" to "normal" as the process being ended uses the toggle button state to determine if the process should continue running.
The problem I'm having at the moment is that the moment the toggle button is pressed, the state changes from "down" to "normal" and thus ends the process before the password box to authenticate the user is shown.
Any advice on how to interrupt the state change of the toggle button when it is clicked?
EDITED!
main.py:
# import kivy modules
from kivy.app import App
from kivy.uix.tabbedpanel import TabbedPanel
from kivy.properties import ObjectProperty
from kivy.config import Config
Config.set('kivy', 'exit_on_escape', '0')
# import self defined backend class
from ProcessPanel import ProcessPanel
class Automation(App):
def __init__(self, **kwargs):
super().__init__(**kwargs)
def build(self):
return AppPanels()
class AppPanels(TabbedPanel):
process_tab = ObjectProperty(None)
process_tab_panel = ObjectProperty(None)
def __init__(self, **kwargs):
super().__init__(**kwargs)
if __name__ == '__main__':
Automation().run()
ProcessPanel.py:
# import kivy modules
from kivy.properties import Clock
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.togglebutton import ToggleButton
from kivy.properties import ObjectProperty
# import self defined backend classes
from ToolStopWindow import ToolStopWindow
class ProcessPanel(BoxLayout):
process_toggle = ObjectProperty()
def __init__(self, **kwargs):
# inherit BoxLayout Attributes and Methods
super().__init__(**kwargs)
self.num = 0
# create the custom query pop up window
self.TSW = ToolStopWindow(passwd="testPassword",
title_text="Are you sure you want to stop the process?",
sub_title_text="Enter Password to Stop Process...",
external_button=self.process_toggle)
self.TSW.confirm_btn.bind(on_release=self.end_process)
self.process_toggle.bind(_do_press=self.toggle_switch_state())
self.process_schedule = []
# Determine if process has been activated
def toggle_switch_state(self):
if self.process_toggle.state == "normal":
self.process_schedule = Clock.schedule_interval(self.my_process, 5)
self.process_toggle._do_unpress()
else:
self.TSW.open()
def my_process(self, dt):
self.num = self.num + 1
print(self.num)
def end_process(self):
self.process_schedule.cancel()
class StartStopToggle(ToggleButton):
def __init__(self, **kwargs):
super().__init__(**kwargs)
def _do_unpress(self):
if (not self.allow_no_selection and
self.group and self.state == 'down'):
return
self._release_group(self)
self.state = 'normal' if self.state == 'down' else 'down'
ToolStopWindow.py:
import time
from kivy.properties import ObjectProperty
from kivy.uix.popup import Popup
class ToolStopWindow(Popup):
passwd_box = ObjectProperty()
passwd = ObjectProperty()
confirm_btn = ObjectProperty()
confirm_btn_callback = ObjectProperty()
cancel_btn = ObjectProperty()
title_text = ObjectProperty()
sub_title = ObjectProperty()
sub_title_text = ObjectProperty()
external_button = ObjectProperty()
def __init__(self, **kwargs):
super().__init__(**kwargs)
self.is_true = False
def check_pass(self):
if self.passwd_box.text == self.passwd:
self.sub_title.text = "Password Correct!"
time.sleep(1)
self.external_button._do_unpress()
self.dismiss()
else:
self.is_true = False
self.passwd_box.text = ""
self.sub_title.text = "Invalid Password!"
return
def reset_label_text(self):
if self.sub_title.text != self.sub_title_text:
self.sub_title.text = self.sub_title_text
Automation.kv:
<AppPanels>:
process_tab: process_tab
process_tab_panel: process_tab_panel
id: Tab_Level
size_hint: 1, 1
pos_hint: {'center_x': .5, 'center_y': .5}
do_default_tab: False
tab_pos: 'top_mid'
tab_width: root.width/5
font_size: 24
TabbedPanelItem:
id: process_tab
text: "Process Tab"
ProcessPanel:
id: process_tab_panel
<ProcessPanel>:
orientation: "vertical"
process_toggle: process_toggle
Button:
text: "normal button"
on_release: root.my_process(self)
StartStopToggle:
id: process_toggle
on_state: root.toggle_switch_state()
<StartStopToggle>:
text: "Start Process Schedule"
font_size: 36
<ToolStopWindow>:
id: close_window
auto_dismiss: False
title: root.title_text
size_hint: 0.8, 0.8
passwd_box: passwd_box
confirm_btn: confirm_btn
cancel_btn: cancel_btn
sub_title: sub_title
BoxLayout:
id: main_panel
orientation: "vertical"
Label:
id: sub_title
text: root.sub_title_text
font_size: 36
TextInput:
id: passwd_box
multiline: False
password: True
on_text: root.reset_label_text()
on_text_validate: root.check_pass()
BoxLayout:
id: Buttons
orientation: "horizontal"
Button:
id: confirm_btn
text: "Confirm!"
on_release: root.check_pass()
Button:
id: cancel_btn
text: "Cancel"
on_release: root.dismiss()
What I would like to do is bind the _do_press function to a function in the ProcessPanel class, but I keep getting an attribute error saying "'None type' object has no attribute 'bind'", i assume this is becuase the id's i'm assigning to the UI objects are assigned after init?
Additionally, there i'm a bit stuck on how to cancel the clock i have created to periodically call the my_process function when the correct password is given.
I hope the addition of this example is helpful!
I would probably subclass the ToggleButton to override the _do_press methods do do the work of opening your popup and then
https://github.com/kivy/kivy/blob/master/kivy/uix/behaviors/togglebutton.py#L112-L115
class ConfirmPopup(Popup):
button = ObjectProperty()
password = StringProperty()
def check_password(self, pass):
if self.ids.password.text == self.password:
self.button._do_unpress()
self.dismiss()
class PasswordCheckedToggleButton(ToggleButton):
def _do_press(self):
ConfirmPopup(button=self, password="secret").open()
def _do_unpress(self):
if (not self.allow_no_selection and
self.group and self.state == 'down'):
return
self._release_group(self)
self.state = 'normal' if self.state == 'down' else 'down'
with something like
<ConfirmPopup>:
title: "password!"
BoxLayout:
orientation: "vertical"
TextInput:
id: password
Button:
text: "it’ a me!"
on_release: root.check_password()
Hi I figured out how to use your answer in my code, posted answer below in case anyone finds it useful.
Not sure why but in a stand alone example, the on_request_close feature isnt working, despite the code being the same as the project i'm working on and it working there, spent a while trying to locate the issue but can't find it.... Either way its working for me now so that even when i try to close the app, i am asked for a password to stop the process before the app will close
main.py:
# import kivy modules
from kivy.app import App
from kivy.core.window import Window
from kivy.uix.tabbedpanel import TabbedPanel
from kivy.properties import ObjectProperty
from kivy.config import Config
Config.set('kivy', 'exit_on_escape', '0')
# import self defined backend class
from StartStopToggle import StartStopToggle
from ProcessPanel import ProcessPanel
from ToolStopWindow import ToolStopWindow
class Automation(App):
def __init__(self, **kwargs):
super().__init__(**kwargs)
def build(self):
Window.bind(on_request_close=self.on_request_close)
return AppPanels()
def on_request_close(self, *args):
if self.root.process_tab_panel.process_toggle.state == "down":
self.root.process_tab_panel.process_toggle.TSW.opening_object = self
self.root.process_tab_panel.process_toggle.TSW.open()
else:
self.stop()
return True
def do_tsw_function(self):
self.stop()
class AppPanels(TabbedPanel):
process_tab = ObjectProperty(None)
process_tab_panel = ObjectProperty(None)
def __init__(self, **kwargs):
super().__init__(**kwargs)
if __name__ == '__main__':
Automation().run()# import kivy modules
from kivy.app import App
from kivy.uix.tabbedpanel import TabbedPanel
from kivy.properties import ObjectProperty
from kivy.config import Config
Config.set('kivy', 'exit_on_escape', '0')
# import self defined backend class
from ProcessPanel import ProcessPanel
class Automation(App):
def __init__(self, **kwargs):
super().__init__(**kwargs)
def build(self):
return AppPanels()
class AppPanels(TabbedPanel):
process_tab = ObjectProperty(None)
process_tab_panel = ObjectProperty(None)
def __init__(self, **kwargs):
super().__init__(**kwargs)
if __name__ == '__main__':
Automation().run()
ProcessPanel.py:
# import kivy modules
from kivy.properties import Clock
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.togglebutton import ToggleButton
from kivy.properties import ObjectProperty
# import self defined backend classes
from ToolStopWindow import ToolStopWindow
class ProcessPanel(BoxLayout):
process_toggle = ObjectProperty()
def __init__(self, **kwargs):
# inherit BoxLayout Attributes and Methods
super().__init__(**kwargs)
self.num = 0
# create the custom query pop up window
self.process_schedule = []
# Determine if process has been activated
def toggle_switch_state(self):
if self.process_toggle.state == "down":
self.process_schedule = Clock.schedule_interval(self.my_process, 5)
self.process_toggle.text = "Stop Process Schedule"
else:
self.process_schedule.cancel()
self.process_toggle.text = "Start Process Schedule"
def my_process(self, dt):
self.num = self.num + 1
print(self.num)
def end_process(self):
self.process_schedule.cancel()
ToolStopWindow.py
import time
from kivy.properties import ObjectProperty
from kivy.uix.popup import Popup
class ToolStopWindow(Popup):
passwd_box = ObjectProperty()
passwd = ObjectProperty()
confirm_btn = ObjectProperty()
confirm_btn_callback = ObjectProperty()
cancel_btn = ObjectProperty()
title_text = ObjectProperty()
sub_title = ObjectProperty()
sub_title_text = ObjectProperty()
opening_object = ObjectProperty()
def __init__(self, **kwargs):
super().__init__(**kwargs)
def check_pass(self):
if self.passwd_box.text == self.passwd:
self.passwd_box.text = ""
self.sub_title.text = "Password Correct!"
time.sleep(1)
self.dismiss()
self.opening_object.do_tsw_function()
else:
self.passwd_box.text = ""
self.sub_title.text = "Invalid Password!"
def reset_label_text(self):
if self.sub_title.text != self.sub_title_text:
self.sub_title.text = self.sub_title_text
StartStopToggle.py:
from kivy.uix.togglebutton import ToggleButton
from ToolStopWindow import ToolStopWindow
class StartStopToggle(ToggleButton):
def __init__(self, **kwargs):
super().__init__(**kwargs)
self.TSW = ToolStopWindow(passwd="password",
title_text="Are you sure you want to stop the process?",
sub_title_text="Enter Password to Stop Process...")
def _do_press(self):
self.TSW.opening_object = self
self.TSW.open()
def do_tsw_function(self):
self._do_actual_press()
def _do_actual_press(self):
if (not self.allow_no_selection and
self.group and self.state == 'down'):
return
self._release_group(self)
self.state = 'normal' if self.state == 'down' else 'down'
Automation.kv
<AppPanels>:
process_tab: process_tab
process_tab_panel: process_tab_panel
id: Tab_Level
size_hint: 1, 1
pos_hint: {'center_x': .5, 'center_y': .5}
do_default_tab: False
tab_pos: 'top_mid'
tab_width: root.width/5
font_size: 24
TabbedPanelItem:
id: process_tab
text: "Process Tab"
ProcessPanel:
id: process_tab_panel
<ProcessPanel>:
orientation: "vertical"
process_toggle: process_toggle
Button:
text: "normal button"
on_release: root.my_process(self)
StartStopToggle:
id: process_toggle
on_state: root.toggle_switch_state()
<StartStopToggle>:
text: "Start Query Schedule"
<ToolStopWindow>:
id: close_window
auto_dismiss: False
title: root.title_text
size_hint: 0.8, 0.8
passwd_box: passwd_box
confirm_btn: confirm_btn
cancel_btn: cancel_btn
sub_title: sub_title
BoxLayout:
id: main_panel
orientation: "vertical"
Label:
id: sub_title
text: root.sub_title_text
font_size: 36
TextInput:
id: passwd_box
multiline: False
password: True
on_text: root.reset_label_text()
on_text_validate: root.check_pass()
BoxLayout:
id: Buttons
orientation: "horizontal"
Button:
id: confirm_btn
text: "Confirm!"
on_release: root.check_pass()
Button:
id: cancel_btn
text: "Cancel"
on_release: root.dismiss()
I am having a hard time changing between keyboard layouts in my app. In the below example I have two text fields and I want one to use a regular keyboard and the other to use a numberpad keyboard. When I click within one text field the keyboard changes, but focus is lost.
Is there a better way of changing a keyboard based on what field currently has focus?
from kivy.config import Config
Config.set('kivy', 'keyboard_mode', 'dock')
from kivy.app import App
from kivymd.app import MDApp
from kivy.lang import Builder
from kivy.core.window import Window
from kivy.clock import Clock
from kivy.properties import ObjectProperty
Window.size = (480, 600)
Window.borderless = False
KV = '''
AnchorLayout:
anchor_x: "center"
anchor_y: "center"
BoxLayout:
orientation: "vertical"
size_hint: 0.9, 0.5
MDTextField:
id: textField
hint_text: "Text field"
mode: "rectangle"
on_focus: app.changeKeyboard(textField, 'keyboard_text.json')
MDTextField:
id: numberField
hint_text: "Number field"
mode: "rectangle"
on_focus: app.changeKeyboard(textField, 'keyboard_number.json')
'''
class MyApp(MDApp):
textField = ObjectProperty()
numberField = ObjectProperty()
def build(self):
return Builder.load_string(KV)
def changeKeyboard(self, widget, layout):
self._keyboard = Window.request_keyboard(self._keyboard_closed, widget)
if self._keyboard.widget:
vkeyboard = self._keyboard.widget
vkeyboard.layout = layout
def _keyboard_closed(self):
print('My keyboard has been closed!')
self._keyboard = None
if __name__ == "__main__":
app = MyApp()
app.run()
In below code I need the button on the edit_button_tab to switch to edit_input_tab. I really need to switch it that way as I need to switch between predefined classes EditButton and EditInput. This is a part of a bigger program with few Buttons in different location of a layout and I cant define them within <MainTabbedPanel> class. I've tried many ways to call switch_to (example in the quotes) but they didn't work.
CODE
from kivy.animation import Animation
from kivy.app import App
from kivy.clock import Clock
from kivy.uix.floatlayout import FloatLayout
from kivy.uix.scrollview import ScrollView
from kivy.uix.tabbedpanel import TabbedPanel, TabbedPanelStrip
from kivy.lang import Builder
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.tabbedpanel import TabbedPanel, TabbedPanelHeader
from kivy.factory import Factory
theRoot = """
#:import Factory kivy.factory.Factory
<EditButton>
orientation: 'vertical'
Button:
text: 'Switch to Edit Screen'
on_press: root.change_tab('edit_screen')
<EditInput>
orientation: 'vertical'
TextInput:
<UnCloseableHeader>
color: 0,0,0,1
disabled_color: self.color
# variable tab_width
text: 'tabx'
size_hint_x: None
width: self.texture_size[0] + 40
BoxLayout:
pos: root.pos
size_hint: None, None
size_y: 20
padding: 3
Label:
id: lbl
text: root.text
<MainTabbedPanel#BoxLayout>
size_hint: (1, 1)
default_tab: edit_button_tab
tab_width: 130
FloatLayout:
EditButton:
id: edit_button
EditInput:
id: edit_input
UnCloseableHeader:
id: edit_button_tab
text: 'Edit'
content: edit_button.__self__
UnCloseableHeader:
id: edit_input_tab
text: 'Edit Tab'
content: edit_input.__self__
MainTabbedPanel:
"""
class EditInput(BoxLayout):
def __init__(self, **kwargs):
super(EditInput, self).__init__(**kwargs)
class EditButton(BoxLayout):
def __init__(self, **kwargs):
super(EditButton, self).__init__(**kwargs)
def change_tab(self, tab):
print('TAB', tab)
#call switch method from MainTabbedPanel
'''the way I've tried
mtp = MainTabbedPanel
mtp.switch_to('edit_input_tab')'''
class MainTabbedPanel(TabbedPanel):
def __init__(self, **kwargs):
super(MainTabbedPanel, self).__init__(**kwargs)
def switch(self, tab):
print("SWITCH TO", tab, self.ids.keys())
self.switch_to(self.ids[tab])
class UnCloseableHeader(TabbedPanelHeader):
pass
Factory.register('UnCloseableHeader', cls=UnCloseableHeader)
sm = Builder.load_string(theRoot)
class TabbedPanelApp(App):
def build(self):
return sm
if __name__ == '__main__':
TabbedPanelApp().run()
EDIT
I've tried with below snippet. It prints IDS of MainTabbedPanel but does not change the tabs.
class EditButton(BoxLayout):
def __init__(self, **kwargs):
super(EditButton, self).__init__(**kwargs)
def change_tab(self, tab):
print('TAB', tab)
MainTabbedPanel.tab = tab
MainTabbedPanel()
#call switch method from MainTabbedPanel
'''the way I've tried
mtp = MainTabbedPanel
mtp.switch_to('edit_input_tab')'''
class MainTabbedPanel(TabbedPanel):
tab = ''
def __init__(self, **kwargs):
super(MainTabbedPanel, self).__init__(**kwargs)
self.tabs_showing = True
if self.tab != '':
Clock.schedule_once(self.switch)
def switch(self, dt):
print("SWITCH TO", self.tab, self.ids.keys())
self.switch_to(self.ids[self.tab])
Use App.get_running_app() to get an instance of your app
Use root to get an instance of your root
Snippets
def change_tab(self, tab):
print('TAB', tab)
mtp = App.get_running_app().root
mtp.switch_to(mtp.ids.edit_input_tab)
Notes
In your kv, you defined a Dynamic class,
<MainTabbedPanel#BoxLayout>. It should be a class rule,
<MainTabbedPanel> because in your Python code, you have defined
class MainTabbedPanel(TabbedPanel): i.e. inheritance mismatch and
class type mismatch.
I have been started to work in kivy recently. The thing what I am doing now is, i have a blank page with a button, when I click that button it navigates to an user input screen. It works fine, but the content comes in a very small input boxes and text as in the picture.
My question is that I want it bigger and centred.
Here is my code:
In python:
from kivy.app import App
from kivy.uix.label import Label
from kivy.uix.gridlayout import GridLayout
from kivy.uix.textinput import TextInput
from kivy.uix.screenmanager import ScreenManager, Screen, FadeTransition
from kivy.uix.widget import Widget
from kivy.lang import Builder
class LoginScreen(GridLayout):
def __init__(self, **kwargs):
super(LoginScreen, self).__init__(**kwargs)
self.cols = 2
self.add_widget(Label(text="Username:"))
self.username = TextInput(multiline=False)
self.add_widget(self.username)
self.add_widget(Label(text="Password:"))
self.password = TextInput(multiline=False, password=True)
self.add_widget(self.password)
self.add_widget(Label(text="Two Factor Auth:"))
self.tfa = TextInput(multiline=False)
self.add_widget(self.tfa)
class MainScreen(Screen):
pass
class AnotherScreen(Screen):
pass
class ScreenManagement(ScreenManager):
pass
presentation = Builder.load_file("screen.kv")
class SimpleKivy(App):
def build(self):
return presentation
if __name__ == "__main__":
SimpleKivy().run()
In kv:
#: import FadeTransition kivy.uix.screenmanager.FadeTransition
ScreenManagement:
transition: FadeTransition()
MainScreen:
AnotherScreen:
<MainScreen>:
name: "main"
Button:
color: 0,1,0,1
font_size: 25
size_hint: 0.3,0.2
text: "Click"
on_release: app.root.current = "other"
pos_hint: {"right":1, "top":1}
<AnotherScreen>:
name: "other"
GridLayout:
LoginScreen
In your screen.kv, you have the LoginScreen inside a GridLayout. Since the LoginSCreen is a GridLayout, you do not need that extra GridLayout.
Just change:
<AnotherScreen>:
name: "other"
GridLayout:
LoginScreen
to:
<AnotherScreen>:
name: "other"
LoginScreen: