I'm trying to make an app that will eventually be able to score cards. One problem I'm trying to solve is how to update the text of a button after pressing or updating it somehow. I'm newer to python/kivy. I've found a couple similar questions, dealing with functions and such, but none dealt with .kv files and separate windows. My code is below.
main.py
import kivy
from kivy.app import App
from kivy.lang import Builder
from kivy.uix.screenmanager import ScreenManager, Screen
class MainWindow(Screen):
pass
class ScoreWindow(Screen):
pass
class WindowManager(ScreenManager):
pass
kv = Builder.load_file("mainkv.kv")
class MyMainApp(App):
def build(self):
return kv
if __name__ == "__main__":
MyMainApp().run()
mainkv.kv
WindowManager:
MainWindow:
ScoreWindow:
<MainWindow>:
name: "main"
GridLayout:
cols: 1
Button:
text: "Quick Score"
on_release:
app.root.current = "score"
root.manager.transition.direction = "left"
<ScoreWindow>:
name: "score"
GridLayout:
cols: 7
Button:
name: "three"
text: "Press to Update"
on_release:
three.text = "Updated"
Button:
text: ""
Button:
text: ""
Button:
text: ""
Button:
text: ""
Button:
text: ""
Button:
text: "Score"
on_release:
app.root.current = "main"
root.manager.transition.direction = "right"
Button:
text: ""
Button:
text: ""
Button:
text: ""
Button:
text: ""
Button:
text: ""
Button:
text: ""
Button:
text: "Go Back"
on_release:
app.root.current = "main"
root.manager.transition.direction = "right"
Your Buttons can refer to themselves in kvlang using the self keyword. So just add another line that says self.text = 'foo' in the on_release: area of your Buttons.
Related
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.
I'm very new to Kivy (been using for about four hours...) and I've hit a wall with popups.
I have a main screen which has four buttons in a float layout. On press down I want the 'MOVE' button to open a popup. Now I've got this working but the popup contains the same four buttons as my mainscreen.
This is my Python code:
def show_movepop():
show = MovePop()
movepopWindow = Popup(title="Move", content=show, size_hint=(None, None),size=(400,400))
movepopWindow.open()
class MovePop(FloatLayout):
pass
class MainWindow(Screen):
def movebtn(self):
show_movepop()
class StatsWindow(Screen):
pass
class WindowManager(ScreenManager):
pass
kv = Builder.load_file("gamegui.kv")
class MainFloatApp(App):
def build(self):
return kv
if __name__ == "__main__":
MainFloatApp().run()
and this is my .kv file:
WindowManager:
MainWindow:
StatsWindow:
<Button>
font_size:40
color:0.3,0.6,0.7,1
size_hint: 0.5, 0.1
<MainWindow>:
name: "mainscreen"
FloatLayout
Button:
text: "MOVE"
id: move
pos_hint: {"x":0, "y":0.1}
on_release: root.movebtn()
Button:
text: "ACTION"
id: action
pos_hint: {"x":0.5, "y":0.1}
Button:
text: "EXAMINE"
id: examine
pos_hint: {"x":0, "y":0}
Button:
text: "STATS"
id: stats
pos_hint: {"x":0.5, "y":0}
on_release:
app.root.current = "statsscreen"
root.manager.transition.direction = "left"
<StatsWindow>:
name: "statsscreen"
Button:
text: "Back"
on_release:
app.root.current = "mainscreen"
root.manager.transition.direction = "right"
<MovePop>:
Button:
text: "!"
pos_hint: {"x":0.1, "y":0.5}
on_release:
Apologies in advance if the above is super dirty, I'm not very efficient :')
All suggestions appreciated!
Okay so I don't know why but it was the FloatLayout that was causing the problem.
Changed
class MovePop(FloatLayout):
pass
to:
class MovePop(AnchorLayout):
pass
BoxLayout also got rid of the duplicate buttons but I couldn't arrange the content on the popup the way I wanted in that layout.
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.
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'
How can I access to the kivy data from MyScreenManager ? How can I access to Hellow or Timer data ? I cant use on_release: root.starttimer() in Hellow.
class Hellow(Screen):
pass
class Timer(Screen):
pass
class MyScreenManager(ScreenManager):
def starttimer(self):
#change text Hellow Button
root_widget = Builder.load_string('''
#:import FadeTransition kivy.uix.screenmanager.FadeTransition
MyScreenManager:
transition: FadeTransition()
Hellow:
Timer:
<Hellow>:
AnchorLayout:
Button:
id: but
size_hint: None, None
size:300,100
text: 'make a foto'
font_size: 30
on_release: app.root.starttimer()
<Timer>:
name: 'Timer'
''')
class ScreenManagerApp(App):
def build(self):
print(self.ids)
return root_widget
if __name__ == '__main__':
ScreenManagerApp().run()
some text for stackoverflow (it says that I need to type more text),
Screen manager is only used to accept screen widgets if you try to add anything else like a button or label then it will throw an exception.
kivy.uix.screenmanager.ScreenManagerException: ScreenManager accepts only Screen widget.
Only one root object is allowed by .kv file In your case, you can access hello or Timer from each other.
<Hellow>:
name: 'hello'
...
Button:
id: but
...
on_release: root.parent.current = 'Timer'
<Timer>:
name: 'Timer'
Button:
text: "Take me back to hellow"
on_release: root.parent.current = 'hello'
but there could be another way too.
<Main>:
BoxLayout:
Button:
text: "Hello"
on_release: sm.current = 'Timer'
on_release: print(lbl.text)
Button:
text: "Timer"
on_release: sm.current = 'Hello'
ScreenManager:
id: sm
Screen:
name: hello
Label:
id: lbl
text: "I am hello"
Screen:
name: timer
Label:
text: "I am timer"
EDIT 1:
As you asked in your comment
class MyScreenManager(ScreenManager):
def __init__(self,**kwargs):
super(MyScreenManager,self).__init__(**kwargs)
def starttimer(self,event):
#print event.text
event.text = "changed text"
<Hellow>:
...
Button:
...
on_release: root.parent.starttimer(self)