how can I remove the added widget from within that widget. am i making any sense? hopefully yes, hehehe...
anyway the simple code consist of buttons and label only.
My aim is if I click the add button it will show the widget which is a label & button. If i want to remove the widget i'll just click the close button in that widget.
but its not closing, its been two days already and i cant find whats the problem and its not giving me any error.
Thanks guys.
from kivy.uix.floatlayout import FloatLayout
from kivy.uix.widget import Widget
from kivy.app import App
from kivy.uix.screenmanager import ScreenManager, Screen
from kivy.lang import Builder
kv_file = Builder.load_string('''
<Screen1>:
BoxLayout:
Button:
on_release: root.add_button(True)
text: 'ADD'
size_hint: .2,.2
<Layout1>:
BoxLayout:
pos: self.x,300
size_hint: .5,.3
Label:
text: 'THIS IS A ADDED WIDGET'
Button:
text: 'Close'
on_release: root.closeBTN()
''')
class Layout1(FloatLayout):
def closeBTN(self):
AddWidget_Layout1().addEmps(True)
class AddWidget_Layout1(Widget):
def __init__(self, **kwargs):
super(AddWidget_Layout1,self).__init__(**kwargs)
self.count = 0
self.layout1 = Layout1()
def addEmps(self,xadd):
if xadd == 1:
self.add_widget(self.layout1)
elif xadd == True:
self.remove_widget(self.layout1)
class Screen1(Screen,AddWidget_Layout1):
def add_button(self,*args):
self.count += 1
print
if self.count == 1:
self.addEmps(1)
class projectApps(App):
def build(self):
return SM
SM = ScreenManager()
SM.add_widget(Screen1())
if __name__ == "__main__":
projectApps().run()
You have a few bugs in your code, first, you are testing xadd for 1 and True which is kinda the same thing:
def addEmps(self,xadd):
if xadd:
self.add_widget(self.layout1)
else: #was elif xadd == True which cannot happen...
self.remove_widget(self.layout1)
I would also change:
def closeBTN(self):
#AddWidget_Layout1().addEmps(True) #BAD! will create a new instance
self.parent.addEmps(False) # this looks better
Finally, I'm not sure why are you doing this since you are already using ScreenManager, so you can just switch to a different screen whenever you need instead of doing this weird widget removal thing ...
I hope this clears most of the issues
Related
I was trying to add the result to a new screen whose content should be dynamic. I tried a few of the trivial ways given in StackOverflow itself but failed to show any content. my code goes as such.
I am entering multiple data, separated by "," without spaces, using text input, and then splitting it which will be stored as a list. The data will be parsed and an equivalent number of labels should be shown on the output screen which I tried but was not successful in execution (line 51-56 in anbs.py).
For example, the input is "I,am,a,good,boy".
The result should be as it will be in the console, i.e. text of each Label should contain an individual item, but nothing goes to the output screen... just a big button that is used to traverse between the screens.
This is my anbs.py file.
from kivy.app import App
from kivy.lang.builder import Builder
from kivy.uix.screenmanager import ScreenManager, Screen
from kivy.uix.popup import Popup
from kivy.uix.label import Label
from kivy.properties import ObjectProperty
from kivy.core.window import Window
from kivy.factory import Factory
Window.size = (600, 600)
class HelpWindow(Screen):
"""
This is a help window. It contains the functionality of all the given boxes
on the main window.
"""
def main_window(self):
sm.current = "main"
class MainWindow(Screen):
"""
This is the main window that contains the main form.
This connects the frontend of the app to the backend
"""
target = ObjectProperty(None)
def v_popup(self):
version_popup()
def help(self):
sm.current = "help"
def output_window(self):
sm.current = "output"
def get_results(self):
#OutputWindow.main(options = options)
out_window = OutputWindow()
out_window.main(self.target.text)
sm.current = "output"
class OutputWindow(Screen):
"""
This is the output window. All the generated results will be seen here.
"""
res = ObjectProperty(None)
res_out = ObjectProperty(None)
def main(self, options):
options = list(options.split(","))
for item in options:
print(item)
self.res_out.add_widget(Label(text=item))
def main_window(self):
sm.current = "main"
class WindowManager(ScreenManager):
pass
def version_popup():
"""
Version Popup Window.
"""
version = "v1.0"
version_text = "this is "+version+" for this app"
vpop = Popup(title="Version",
content=Label(text=version_text),
size_hint=(None, None), size=(400, 400))
vpop.open()
### main builder and WindowManager object
kv = Builder.load_file("start.kv")
sm = WindowManager()
### Adding screens to widget
screens = [MainWindow(name="main"), HelpWindow(name="help"), OutputWindow(name="output")]
for screen in screens:
sm.add_widget(screen)
sm.current = "main"
### main working
class AnbsApp(App):
def build(self):
return sm
if __name__ == '__main__':
AnbsApp().run()
and my start.kv file looks like this
<HelpWindow>
name:"help"
Button:
id:ms
text:"Main Screen"
on_release:
root.manager.transition.direction = "left"
root.main_window()
<MainWindow>
name:"main"
target : target
GridLayout:
cols:1
GridLayout:
cols:3
row_force_default: True
row_default_height: 50
Button:
id:hp
text:"Help"
on_release:
root.manager.transition.direction = "right"
root.help()
Button:
id:version
text: "Version"
on_release:
root.v_popup()
GridLayout:
cols:2
row_force_default: True
row_default_height: 30
Label:
text:"Target *"
TextInput:
id:target
multiline:False
GridLayout:
cols:3
row_force_default: True
row_default_height: 50
Label:
text:""
Button:
text:"Submit"
on_release:
root.get_results()
Label:
text:""
<OutputWindow>
name:"output"
res_out:res_out
GridLayout:
id:res_out
cols : 1
Button:
id:ms
text:"Main Screen"
on_release:
root.manager.transition.direction = "right"
root.main_window()
I can't really say whats the major point I am missing in it.
Your code:
def get_results(self):
#OutputWindow.main(options = options)
out_window = OutputWindow()
out_window.main(self.target.text)
sm.current = "output"
is creating a new instance of OutputWindow in the line:
out_window = OutputWindow()
and then calling the main() method of that new instance. However, that new instance is not in your GUI, so no effect is observed. To correct that, change the code to use the instance of OutputWindow that is in your GUI:
def get_results(self):
out_window = self.manager.get_screen('output') # get OutputWindow instance
out_window.main(self.target.text)
sm.current = "output"
You will also need to adjust the size/position of the Button in the OutputWindowso that it does not completely cover the GridLayout.
I am hoping to eventually create a button to pause/start/end a pong app I built as a learning exercise. However, to understand the basics of how to create a button in the first place, and assign a response to it I am just wanting to create a button that notifies me every time the button state changes. Here is the python code I have so far:
import kivy.uix.button as kb
from kivy.app import App
from kivy.uix.widget import Widget
class Button_Widget(Widget):
def callback(instance, value):
print('The button <%s> state is <%s>' % (instance, value))
btn1 = kb.Button(text='Hello World 1')
btn1.bind(on_press=callback)
class ButtonApp(App):
def build(self):
button = Button_Widget()
return button
with the associated kv file:
#:kivy 1.0.9
<Button_Widget>:
size: 100, 100
canvas:
Rectangle:
pos = self.pos
size = self.size
So far the only resources I have found are these (1 and 2) Kivy turorials, which aren't too helpful. Or at least, I don't understand their language enough yet for them to be useful
Let's see the simplest code to create a button in kivy
from kivy.app import App
from kivy.uix.button import Button
class your_app_name(App):
def build(self):
button = Button(text="Button")
return button
your_app_name().run()
You can also add command or event to a button by adding on_press= function_name
Solution
In the class Button_Widget(), you have to override the constructor, __init__() so that you can add the button widget to the root widget. Please refer to the example for details.
References
Programming Guide » Kivy Basics » Create an application
Programming Guide » Kv language
Kivy Language
Event dispatcher » bind() Bind an event type or a property to a callback.
Example
main.py
import kivy.uix.button as kb
from kivy.app import App
from kivy.uix.widget import Widget
class Button_Widget(Widget):
def __init__(self, **kwargs):
super(Button_Widget, self).__init__(**kwargs)
btn1 = kb.Button(text='Hello World 1')
btn1.bind(on_press=self.callback)
self.add_widget(btn1)
def callback(self, instance):
print('The button %s state is <%s>' % (instance, instance.state))
class ButtonApp(App):
def build(self):
return Button_Widget()
if __name__ == "__main__":
ButtonApp().run()
button.kv
#:kivy 1.10.1
<Button_Widget>:
size: 100, 100
canvas:
Rectangle:
pos: self.pos
size: self.size
Output
I'm attempting to create a stopwatch in Kivy. I've completed a skeleton on Sublime Text 3 (as shown in the code below). When I run the code on Sublime Text, a window opens, but Python crashes in 4.1s.
Here is the code in question:
import kivy
from kivy.app import App
from kivy.uix.gridlayout import GridLayout
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.label import Label
from kivy.clock import Clock
from kivy.properties import NumericProperty
from kivy.lang import Builder
import time
class CrudeTimerGrid(GridLayout):
# Initialise timer with input start time
def __init__(self,start_time):
time = NumericProperty(start_time)
def tick(self):
if self.time > 0:
self.time -= 1
else:
pass
def start(self):
Clock.schedule_interval(self.tick,1)
def pause(self):
Clock.unschedule()
# incomplete code
def reset(self):
pass
class CrudeTimerApp(App):
def build(self):
# Testing timer by initialising timer with 20 seconds
return CrudeTimerGrid(20)
Builder.load_string('''
<CrudeTimerGrid>
id: timer
rows: 2
# insert formatting here
BoxLayout:
Label:
text: timer.time
BoxLayout:
Button:
text: "Start"
on_press: timer.start()
Button:
text: "Pause"
on_press: timer.pause()
Button:
text: "Reset"
on_press: timer.reset()
''')
CrudeTimerApp().run()
Newbie at StackOverflow too, so please let me know if any other info is needed. Thanks for your help!
Main problem is here:
def __init__(self,start_time):
time = NumericProperty(start_time)
You should define Kivy properties at class level, please read this. Code'll stop crash if you change it like this:
class CrudeTimerGrid(GridLayout):
time = NumericProperty(0)
There're also few other changes you should do to make it finally work, here's full code version:
import kivy
from kivy.app import App
from kivy.uix.gridlayout import GridLayout
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.label import Label
from kivy.clock import Clock
from kivy.properties import NumericProperty
from kivy.lang import Builder
import time
class CrudeTimerGrid(GridLayout):
time = NumericProperty(0)
def tick(self, *_):
if self.time > 0:
self.time -= 1
else:
pass
def start(self, *_):
self.cb = Clock.schedule_interval(self.tick,1)
def pause(self):
Clock.unschedule(self.cb)
# incomplete code
def reset(self, *_):
pass
class CrudeTimerApp(App):
def build(self):
# Testing timer by initialising timer with 20 seconds
return CrudeTimerGrid(time=20)
Builder.load_string('''
<CrudeTimerGrid>
id: timer
rows: 2
# insert formatting here
BoxLayout:
Label:
text: str(timer.time)
BoxLayout:
Button:
text: "Start"
on_press: timer.start()
Button:
text: "Pause"
on_press: timer.pause()
Button:
text: "Reset"
on_press: timer.reset()
''')
CrudeTimerApp().run()
Upd:
Any idea why 2 arguments are input into tick in the first place?
tick passed to Clock.schedule_interval to be called. This function schedules it's callback with additional parameter (as many other functions in Kivy also do). You can read a bit more about it in documentation.
You defined self.cb in order to reference it in Clock.unschedule,
correct?
You can schedule many different functions with different intervals calling Clock.schedule_interval multiple times. But how can Clock.unschedule know which concrete of them to unschedule? In order to make Clock.unschedule know what to unschedule you should pass to it value returned by Clock.schedule_interval. Here's documentation section where this mechanism described.
I am trying to display some output in the corresponding text input boxes but when I click on the update button output should be in the left Input box that's working but when I click on Updatee button output is displayed on left text input box itself(it overwrites whatever is there in the left input area).
When I click on Updatee it should display in the right box and when update is clicked output should be in the left input box or area. And same with the clear function which is clearing only the left box I want it to clear both. Also I want only one button i.e. just Update to display in the corresponding boxes.
This is the Python file:
from kivy.app import App
from kivy.uix.gridlayout import GridLayout
class DemoGridLayout(GridLayout):
def update(self, query):
if query:
a = query + str("Area 1")
self.display.text = a
def updatee(self, query):
if query:
a = query + str("Area 2")
self.display.text = a
def clear(self):
self.display.text = ""
class DemoApp(App):
def build(self):
return DemoGridLayout()
demoApp = DemoApp()
demoApp.run()
Kivy File(as demo.kv) :
<CustButton#Button>:
font_size: 28
<DemoGridLayout>:
id:test
display:entry
rows:3
cols:2
padding:10
spacing:10
BoxLayout:
TextInput:
id: entry
font_size:20
multiline:True
BoxLayout
TextInput:
id: entrye
font_size:20
multiline:True
CustButton:
id: b1
size_hint_y:0.1
text:"Update"
on_press:test.update(entry.text)
CustButton:
id: b2
size_hint_y:0.1
text:"Updatee"
on_press:test.updatee(entrye.text)
CustButton:
size_hint_y:0.1
size_hint_x:0.5
text:"Clear"
on_press:test.clear()
Here is the updated code.You should read official docs to get your doubts clarified.In process you learn more things.
from kivy.app import App
from kivy.uix.gridlayout import GridLayout
from kivy.properties import ObjectProperty
class DemoGridLayout(GridLayout):
entry = ObjectProperty(None)
entrye = ObjectProperty(None)
def update(self, query):
if query:
a = query + str("Area 1")
self.entry.text = a
def updatee(self, query):
if query:
a = query + str("Area 2")
self.entrye.text = a
def clear(self):
self.display.text = ""
class DemoApp(App):
def build(self):
return DemoGridLayout()
if __name__ == "__main__":
demoApp = DemoApp()
demoApp.run()
demo.kv =>
<CustButton#Button>:
font_size: 28
<DemoGridLayout>:
id:test
display:entry
rows:3
cols:2
padding:10
spacing:10
entry: entry
entrye: entrye
TextInput:
id: entry
font_size:20
multiline:True
TextInput:
id: entrye
font_size:20
multiline:True
CustButton:
id: b1
size_hint_y:0.1
text:"Update"
on_press:test.update(entry.text)
CustButton:
id: b2
size_hint_y:0.1
text:"Updatee"
on_press:test.updatee(entrye.text)
CustButton:
size_hint_y:0.1
size_hint_x:0.5
text:"Clear"
on_press:test.clear()
i have intentionally left clear part for you to work out.
I didn't clearly get you what you were trying to ask but yes i will provide you minimal code that might help to answer your question.I designed this code replicating your case.If you are newbie this link will help you get started.Keep on using Kivy it is awesome.
from kivy.app import App
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.button import Button
from kivy.lang import Builder
Builder.load_string('''
#: import Platform kivy.utils.platform
<Interface>:
orientation: 'vertical'
TextInput:
id:label
hint_text: "enter text"
Button:
text:"change label and text_hint"
on_press:label2.hint_text=label.text
Label:
id:label3
text:label.text
TextInput:
id:label2
text_hint:label.text
''')
class Interface(BoxLayout):
pass
class SampleApp(App):
def build(self):
return Interface()
if __name__ == "__main__":
app = SampleApp()
app.run()
I am trying to update a label in python. It is a simple Guess the num game. Currently it prints the Computer responses in PC but I want it to print those to a label.
here is the main .py file
from kivy.app import App
from kivy.uix.boxlayout import BoxLayout
import random
secret=random.randint(1,100)
class Application(BoxLayout):
label1=""
def button_press(self):
global label1
if (int(self.user_guess.text)<secret):
print("Higher")
self.label1="Higher"
elif(int(self.user_guess.text)>secret):
print("Lower")
self.label1="Lower"
elif(int(self.user_guess.text)==secret):
print("You WOn")
self.label1="You WOn"
class WeatherApp(App):
pass
if __name__ == '__main__':
WeatherApp().run()
the .kv file
Application:
<Application>:
size:(480,30)
user_guess:guess
size_hint:(None,None)
text:""
orientation: "vertical"
BoxLayout:
Button:
text:'Play'
on_press:root.button_press()
TextInput:
id:guess
text:''
Label:
text:root.label1
I think you should use
self.label1.text="Higher"