Widgets ( button , inputtext etc. ) inside screen is not working - python

I am trying to put some text box and button inside screen but seems that it doesn't work. Any suggestion or issue in code? when running main.py the textinput and first button and label is not there
Phone.kv
<Phone>:
orientation: 'vertical'
ScreenManager:
size_hint: 1, 1
id: _screen_manager
Screen:
name: 'screen1'
Label:
markup: True
text: 'manish'
TextInput:
text: 'Hi Kivy'
Button:
text: 'Go to Screen 1'
on_press:
_screen_manager.current = 'screen1'
Button:
text: 'Go to Screen 2'
on_press:
root.login()
_screen_manager.current = 'screen2'
Screen:
name: 'screen2'
GridLayout:
cols: 3
padding: 50
Button:
text: "1"
main.py
from kivy.app import App
from kivy.lang import Builder
from kivy.uix.floatlayout import FloatLayout
import time
class Phone(FloatLayout):
def login(self):
print "before"
time.sleep(2)
print "after"
class PhoneApp(App):
def build(self):
return Phone()
if __name__ == '__main__':
PhoneApp().run()

Everything is probably there, just all on top of each other since Screen by default places its children to fill itself.
Try something like the following, which uses a boxlayout that should place its children in different places.
Screen:
name: 'screen1'
BoxLayout:
orientation: 'vertical'
Label:
markup: True
text: 'manish'
TextInput:
text: 'Hi Kivy'
Button:
text: 'Go to Screen 1'
on_press:
_screen_manager.current = 'screen1'
Button:
text: 'Go to Screen 2'
on_press:
root.login()
_screen_manager.current = 'screen2'

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()

Adding a class(screen) to a class(widget) in kivy

I'm trying to make an app in where the top_part of the app there are a Spinner,Label and Button and these 3 are inside a GridLayout with 3 columns. When I click in the spinner. It's displays some choices such as: "Catalogue", "Buy", "Payment Methods". I want that every time I press the Spinner and select a choice, change the screen that is below of this GridLayout. In these case would be 3 screens because they are 3 choices ("Catalogue", "Buy", "Payment Methods"). and these should be below of BoxLayout in MyLayout(U can see it in the kv.code)
The screens are not working, and I got an error when run the app(invalid class). Just work the part of MyLayout, but from ScreenManager and Screens are not working, I don't know how to fix it.
Py.file
from kivy.app import App
from kivy.uix.widget import Widget
from kivy.lang import Builder
from kivy.core.spelling import Spelling
from kivy.uix.screenmanager import ScreenManager, Screen
Builder.load_file('test2.kv')
class MyLayout(Widget):
def spinner_clicked(self,value):
self.ids.Label1.text= f'You selected: {value}'
#Definine our different screens
class FirstWindow(Screen):
pass
class SecondWindow(Screen):
pass
class WindowManager(ScreenManager):
pass
class AwesomeApp(App):
def build(self):
return MyLayout()
if __name__ == '__main__':
AwesomeApp().run()
This is the kv.file
<MyLayout>
BoxLayout:
orientation:"vertical"
size: root.width, root.height
GridLayout:
cols:3
Spinner:
id: spinner_id
text: "Menu"
values: ["Catalogue","Buy","Payment Methods", "Contact"]
on_text: root.spinner_clicked(spinner_id.text)
Label:
id: Label1
text: "My Panel"
Button:
text:"Buy"
Label:
id: Label2
text: "My Panel"
WindowManager:
FirstWindow:
SecondWindow:
<FirstWindow>:
name: "first"
BoxLayout:
orientation: "vertical"
size: root.width, root.height
Label:
text: "First Screen"
font_size: 32
Button:
text: "Next Screen"
font_size: 32
on_release:
app.root.current= "second"
root.manager.transition.direction= "left" #up
<SecondWindow>:
name: "second"
BoxLayout:
orientation: "vertical"
size: root.width, root.height
Label:
text: "Second Screen"
font_size: 32
Button:
text: "Go Back"
font_size: 32
on_release:
app.root.current= "first"
root.manager.transition.direction= "right"
As #ApuCoder suggested, you can change MyLayout to extend BoxLayout, and add the WindowManager to that. Just change the definition of MyLayout:
class MyLayout(BoxLayout):
def spinner_clicked(self,value):
self.ids.Label1.text= f'You selected: {value}'
And modify your kv to use the modified MyLayout:
<MyLayout>
orientation:"vertical"
GridLayout:
cols:3
Spinner:
id: spinner_id
text: "Menu"
values: ["Catalogue","Buy","Payment Methods", "Contact"]
on_text: root.spinner_clicked(spinner_id.text)
Label:
id: Label1
text: "My Panel"
Button:
text:"Buy"
# add ScreenManager and Screens
WindowManager:
FirstWindow:
SecondWindow:
<FirstWindow>:
name: "first"
BoxLayout:
orientation: "vertical"
Label:
text: "First Screen"
font_size: 32
Button:
text: "Next Screen"
font_size: 32
on_release:
root.manager.current= "second" # use root.manager instead of app.root
root.manager.transition.direction= "left" #up
<SecondWindow>:
name: "second"
BoxLayout:
orientation: "vertical"
Label:
text: "Second Screen"
font_size: 32
Button:
text: "Go Back"
font_size: 32
on_release:
root.manager.current= "first" # use root.manager instead of app.root
root.manager.transition.direction= "right"

Windwomanager with TappedPanels

main.py:
from kivy.app import App
from kivy.lang import Builder
from kivy.uix.screenmanager import ScreenManager, Screen
from kivy.uix.tabbedpanel import TabbedPanel
class Test(TabbedPanel):
pass
class MainWindow(Screen):
pass
class SecondWindow(Screen):
pass
class WindowManager(ScreenManager):
pass
kv = Builder.load_file("settings.kv")
class MyMainApp(App):
def build(self):
return kv
if __name__ == "__main__":
MyMainApp().run()
settings.kv:
WindowManager:
MainWindow:
SecondWindow:
Test:
<MainWindow>:
name: "main"
GridLayout:
cols:2
Button:
text: "New Order"
on_release:
app.root.current = "tabs"
root.manager.transition.direction = "left"
Button:
text: "Basket"
on_release:
app.root.current = "second"
root.manager.transition.direction = "left"
<SecondWindow>:
name: "second"
Button:
text: "Go Back"
on_release:
app.root.current = "main"
root.manager.transition.direction = "right"
<Test>:
name: "test"
size_hint: .5, .5
pos_hint: {'center_x': .5, 'center_y': .5}
do_default_tab: False
TabbedPanelItem:
text: 'first tab'
Label:
text: 'First tab content area'
TabbedPanelItem:
text: 'tab2'
BoxLayout:
Label:
text: 'Second tab content area'
Button:
text: 'Button that does nothing'
TabbedPanelItem:
text: 'tab3'
RstDocument:
text:
'\\n'.join(("Hello world", "-----------",
"You are in the third tab."))
I want a transition that starts with a button press that leads to a tabbed overlay, However the screenmanager doesnt accept the use of tabbedpanel
kivy.uix.screenmanager.ScreenManagerException: ScreenManager accepts only Screen widget.
How can I achieve this effect, I am new to kivy. I want one button press to go to a another normal screen while the other one to open a tabbed screen,
Just add a TabblePanel to one of your Screens.
<BlaBlaScreen>:
name: 'BlaBla'
TabbedPanel:
do_default_tab: False
TabbedPanelItem:
text: "something"
Just put your TabbedPanel in a Screen.
Good day. Use your screen manager to switch between each screen. The screen then contains your unique layout of whatever you placed in it. That could include a screen with tabs.

Kivy Python: buttons and classes for multiple screens

I have a problem with my Kivy Python Code. I have 2 screens: 1st is to navigate to the second screen and on the 2nd screen there is a button to add text to a scrollview...navigating is working but it does not add any text to the scrollview...I think I need some help here! AttributeError: 'super' object has no attribute 'getattr'
import kivy
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.button import Button
from kivy.uix.screenmanager import ScreenManager, Screen
from kivy.clock import Clock, mainthread
from kivy.core.window import Window
from kivy.uix.scrollview import ScrollView
from kivy.effects.scroll import ScrollEffect
from kivy.lang import Builder
Builder.load_string("""
<MenuScreen>:
name: 'mainmenu'
BoxLayout:
spacing: 1
orientation: "vertical"
Label:
text: "MAIN MENU"
Button:
text: 'Go to Screen 2'
on_release:
root.manager.current = 'screen2'
root.manager.transition.direction = "left"
Button:
text: 'Quit'
on_release: root.manager.current = app.exit_software()
<Screen2>:
name: 'screen2'
BoxLayout:
spacing: 1
orientation: "vertical"
ScrollView:
id: scroll_view
always_overscroll: False
BoxLayout:
size_hint_y: None
height: self.minimum_height
orientation: 'vertical'
Label:
id: label
text: "You can add some Text here by pressing the button"
size_hint: None, None
size: self.texture_size
Button:
text: 'Add text!'
size_hint_y: 0.1
on_release: app.add_text()
Button:
text: 'Back to main menu'
size_hint_y: 0.1
on_release:
root.manager.current = 'mainmenu'
root.manager.transition.direction = "right"
""")
# Declare both screens
class MenuScreen(Screen):
pass
class Screen2(Screen):
pass
class AddTextApp(App):
def __init__(self,**kwargs):
super().__init__(**kwargs)
def build(self):
# Create the screen manager
sm = ScreenManager()
sm.add_widget(MenuScreen(name='mainmenu'))
sm.add_widget(Screen2(name='screen2'))
return sm
def add_text(self):
self.root.ids.label.text += f"Some new Text\n"
self.root.ids.scroll_view.scroll_y = 0
def exit_software(self):
App.get_running_app().stop()
if __name__ == '__main__':
AddTextApp().run()
Thank you very much in advance!
The error occurred because self.root.ids gets access to widgets located in the root widget of the main class. To access the secondary screen elements, you need to add it to the main class (in your case, in ScreenManager) and set its id. Also, you have a lot of imported excess, so that it is clearly visible, I advise you to use Pycharm or something like that.
from kivy.app import App
from kivy.uix.screenmanager import Screen
from kivy.lang import Builder
kv = """
<MenuScreen>:
name: 'mainmenu'
BoxLayout:
spacing: 1
orientation: "vertical"
Label:
text: "MAIN MENU"
Button:
text: 'Go to Screen 2'
on_release:
root.manager.current = 'screen2'
root.manager.transition.direction = "left"
Button:
text: 'Quit'
on_release: root.manager.current = app.exit_software()
<Screen2>:
name: 'screen2'
BoxLayout:
spacing: 1
orientation: "vertical"
ScrollView:
id: scroll_view
always_overscroll: False
BoxLayout:
size_hint_y: None
height: self.minimum_height
orientation: 'vertical'
Label:
id: label
text: "You can add some Text here by pressing the button"
size_hint: None, None
size: self.texture_size
Button:
text: 'Add text!'
size_hint_y: 0.1
on_release: app.add_text()
Button:
text: 'Back to main menu'
size_hint_y: 0.1
on_release:
root.manager.current = 'mainmenu'
root.manager.transition.direction = "right"
ScreenManager:
MenuScreen:
id: menu_scr
Screen2:
id: scr_2
"""
class MenuScreen(Screen):
pass
class Screen2(Screen):
pass
class AddTextApp(App):
def __init__(self, **kwargs):
super().__init__(**kwargs)
def build(self):
return Builder.load_string(kv)
def add_text(self):
self.root.ids.scr_2.ids.label.text += f"Some new Text\n"
self.root.ids.scr_2.ids.scroll_view.scroll_y = 0
#staticmethod
def exit_software():
App.get_running_app().stop()
if __name__ == '__main__':
AddTextApp().run()

Only "else statement" shown when running app with python/kivy

I have been working on an app with Kivy that receives 0, 1 or 2 as text input by the user and a label on the final screen shows a text which should differ based on the received input. It does not present with any errors any longer, but the final screen will only show the "else" text ("Bad Luck") even when the requirements of the "if statement" are met.
By searching similar questions, I tried using an "input_filter" for integers in case it resolved the issue, but it didn't.
I am a beginner with no programming background, so please feel free to be as elaborate as you like in your answers. Thank you in advance for your time and any ideas/recommendations you may share. Following are the codes of the .py and .kv files:
.py file:
import kivy
from kivy.app import App
from kivy.lang import Builder
from kivy.uix.label import Label
from kivy.uix.gridlayout import GridLayout
from kivy.uix.textinput import TextInput
from kivy.uix.button import Button
from kivy.uix.widget import Widget
from kivy.uix.screenmanager import ScreenManager, Screen
from kivy.properties import NumericProperty, StringProperty, NumericProperty
class MainWindow(Screen):
pass
class SecondWindow(Screen):
pass
class ThirdWindow(Screen):
pass
class FourthWindow(Screen):
pass
class WindowManager(ScreenManager):
pass
class MyApp(App):
def build(self):
kv = Builder.load_file("my.kv")
return kv
if __name__=="__main__":
MyApp().run()
.kv file:
WindowManager:
MainWindow:
SecondWindow:
ThirdWindow:
FourthWindow:
<MainWindow>:
name: "main"
GridLayout:
cols:1
rows:2
Label:
text: "stuff"
Button:
text: "stuff"
on_release:
app.root.current = "second"
root.manager.transition.direction = "left"
<SecondWindow>:
name: "second"
GridLayout:
cols:1
rows:2
GridLayout:
cols:2
Label:
text: "stuff"
TextInput:
id: ti_a
multiline:False
Label:
text: "stuff"
TextInput:
id: ti_b
multiline:False
Label:
text: "stuff"
TextInput:
id: ti_c
multiline:False
Label:
text: "stuff"
TextInput:
id: ti_d
multiline:False
Label:
text: "stuff"
TextInput:
id: ti_e
multiline:False
GridLayout:
cols:2
Button:
text: "stuff"
on_release:
app.root.current = "third"
root.manager.transition.direction = "left"
Button:
text: "Back"
on_release:
app.root.current = "main"
root.manager.transition.direction = "right"
<ThirdWindow>:
name: "third"
GridLayout:
cols:1
rows:2
GridLayout:
cols:2
Label:
text: "stuff"
TextInput:
id: ti_f
multiline:False
GridLayout:
cols:2
Button:
text: "stuff"
on_release:
app.root.current = "fourth"
root.manager.transition.direction = "left"
Button:
text: "Back"
on_release:
app.root.current = "second"
root.manager.transition.direction = "right"
<FourthWindow>:
name: "fourth"
Label:
text: "Stuff" if root.manager.get_screen("second").ids.ti_a.text == "0" and root.manager.get_screen("second").ids.ti_b.text == "0" and root.manager.get_screen("second").ids.ti_c.text == "0" and root.manager.get_screen("second").ids.ti_d.text == "0" and root.manager.get_screen("second").ids.ti_e.text == "1" and root.manager.get_screen("third").ids.ti_f.text == "0" else "Bad Luck"
The problem is that kivy doesn't recognize the expression:
root.manager.get_screen("second").ids.ti_a.text
as a property that it can bind to, so the value of Label text in your FourthWindow is only evaluated once (when the FourthWindow is created). Any changes to the other Labels in your app will have no effect on FourthWindow. See the documentation.
The fix is to write your own code to update that Label by adding an id to that Label:
<FourthWindow>:
name: "fourth"
Label:
id: lab
text: ""
And adding a on_pre_enter() method to FourthWindow:
class FourthWindow(Screen):
def on_pre_enter(self, *args):
if self.manager.get_screen("second").ids.ti_a.text == "0" and \
self.manager.get_screen("second").ids.ti_b.text == "0" and \
self.manager.get_screen("second").ids.ti_c.text == "0" and \
self.manager.get_screen("second").ids.ti_d.text == "0" and \
self.manager.get_screen("second").ids.ti_e.text == "1" and \
self.manager.get_screen("third").ids.ti_f.text == "0":
self.ids.lab.text = 'Stuff'
else:
self.ids.lab.text = 'Bad Luck'
This will evaluate your expression and set the text each time just before the FourthWindow is displayed.

Categories

Resources