remove_widget kivy do not remove by name - kivy

I have this code, and I can’t remove the widget when I use the name of this widget: MainApp(). m.remove_widget (Butt()).
I understand that I am accessing this widget incorrectly, but I do not understand how to do it correctly.
Tell me how to remove a widget using its name?
from kivy.app import App
from kivy.uix.widget import Widget
from kivy.uix.colorpicker import ColorPicker
from kivy.uix.floatlayout import FloatLayout
from kivy.uix.button import Button
class Butt(Button):
def add_wid1(self):
MainApp.m.add_widget(Box())
MainApp.m.add_widget(Butt1())
class Butt1(Button):
def on_press(self):
print('111')
MainApp().m.remove_widget(MainApp().m.children[1]) #this code works
MainApp().m.remove_widget(Butt()) #this code not working
class Box (ColorPicker):
size_hint=.50, .25
class Pict (Widget):
pass
class MainApp (App):
m = FloatLayout()
def build (self):
pic = Pict()
MainApp.m.add_widget(pic)
MainApp.m.add_widget(Butt())
return MainApp.m
if __name__ == '__main__':
MainApp().run()

You must use the instance of the Butt that you want to remove. An easy way to do it is to save a reference to that Butt in your build method:
self.butt = Butt()
MainApp.m.add_widget(self.butt)
and then remove it with:
app = App.get_running_app()
MainApp.m.remove_widget(app.butt)

Related

Invalid data after declaration Kivy Tutorial #5 - Object Properties and .kv Continued

I am brand new to coding and am working my way thru the tech with tim kivy youtube turtorials. I am following his code for the most part but am trying to tailor it to the app I'm trying to develop. I am getting the following error message and have no idea how to fix it.
line 3:
...
1:<MyGrid>
2:
>> 3: FirstName: FirstName
4: LastName: LastName
5: Email: Email
...
Invalid data after declaration
Process finished with exit code 1
This is the code I'm entering. I have no idea how to even look for the problem.
Any advise on debugging or learning is greatly appreciated!
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.bubble import Button
from kivy.uix.widget import Widget
from kivy.properties import ObjectProperty
class MyGrid(Widget):
FirstName = ObjectProperty(None)
LastName = ObjectProperty(None)
Email = ObjectProperty(None)
Address = ObjectProperty(None)
Bankname = ObjectProperty(None)
AccountNumber = ObjectProperty(None)
RoutingNumber = ObjectProperty(None)
class MyApp(App):
def build(self):
return MyGrid()
if __name__ == "__main__":
MyApp().run()
Make your property names begin with a lowercase letter, and make sure your widget classes begin with an uppercase letter. Kv language uses this to distinguish between them, and by not following that rule you have it looking for a widget named FirstName.

Why app code does not recognize design code?

I'm fairly new into programming so this may be lousy question.
I'm watching tutorials of kivy programming (https://youtu.be/k4QCoS-hj-s?list=PLCC34OHNcOtpz7PJQ7Tv7hqFBP_xDDjqg) and I'm stuck at design language code.
Basically, I'm trying to write a design language code (my.kv) for an app enter code here(design.py) which should be connected with this lines in design.py, because of "My" in class:
class MyApp(App):
def build(self):
return MyGridLayout()
Also, line in design.py:
class MyGridLayout(Widget):
is connected to first line in my.kv:
<MyGridLayout>
However, it seems design.py does not recognize it, even though they are saved in the same folder.
I was thinking problem may be in different operating systems (Linux-Windows) because of types of brackets, but I don't know what is the Windows parallel to Linux angle brackets.
Any thoughts?
EDIT
I tried what #NameKhan72 proposed:
from kivy.lang import Builder
class MyApp(App):
def build(self):
kv = Builder.load_file('my.kv')
return MyGridLayout()
but still getting error - "no such file or directory: "my.kv"".
EDIT2
I found the mistake. Of course, it was connected to my experience in programming. I didn't put ":" at the end of "". Now there is no error but after opening app I get a black screen.
I tried everything I found on the web but nothing so far.
This is code:
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.widget import Widget
from kivy.properties import ObjectProperty
class MyGridLayout(Widget):
name = ObjectProperty(None)
pizza = ObjectProperty(None)
color = ObjectProperty(None)
def press(self):
name = self.name.text
pizza = self.pizza.text
color = self.color.text
print("Hello " + name + ", you like " + pizza + "pizza, and your favorite color is " + color + ".")
self.name.text =""
self.pizza.text =""
self.color.text =""
class MyApp(App):
def build(self):
return MyGridLayout()
if __name__ == "__main__":
MyApp().run()
This is design code in my.kv:
<MyGridLayout>:
name:name
pizza:pizza
color:color
GridLayout:
cols:1
size: root.width, root.height
GridLayout:
cols:2
Label:
text: "Name"
TextInput:
id: name
multiline:False
Label:
text: "Favorite pizza"
TextInput:
id: pizza
multiline:False
Label:
text: "Favorite color"
TextInput:
id: color
multiline:False
Button:
text: "Submit"
font_size: 32
on_press: root.press()
Is it typo or what? I rewrited the whole code 2x to be sure but still getting black screen.
You need to load the kv-file into python:
from kivy.lang import Builder
class MyApp(App):
def build(self):
kv = Builder.load_file('my.kv')
return MyGridLayout()
The answer my friend is blowing in the wind.
Nope, my problem was saving in wrong file extension. While saving, I writed my.kv but my PC saved it as my.kv.py. That was the reason why code didn't recognize design code.
Thanks for help, surely it'll help me in the future :)
you should use Builder.load_file("filename.kv") or `Builder.load_string(""
""")but to import it usefrom kivy.lang import Builder`

Accessing id/widget of different class from a kivy file (.kv) using Kivy's clock?

I've spent the day working with the code from How to access id/widget of different class from a kivy file (.kv)? I've paired it down to the simplest code I could because what I want to do is use Kivy's Clock function to change the text for me instead of clicking the button.
As best as I can understand the code that changes the text should go on Line 38 of the program but all the code I tried stopped executing because it could not access the text to change it. The clock function is working in the code provided.
I've left the button press active but it's the Clock code that I want to change the text. I was wondering if someone knows the solution.
Thanks in advance.
....brad....
from kivy.app import App
from kivy.lang import Builder
from kivy.uix.boxlayout import BoxLayout
from kivy.clock import Clock
from kivy.properties import ObjectProperty
Builder.load_string("""
<SingleScreen>:
id: single_screen
orientation: 'vertical'
Button:
text: "You Can Change Me By Button Press Here But I Really Want To Be Changed By Kivy's Clock Function"
on_release: root.rooted()
Change_Label:
id: gb
<Change_Label>:
_python_access: ChangeLabel
Label:
id: ChangeLabel
text: "I'm Gonna Change."
""")
class SingleScreen(BoxLayout):
def rooted(self):
self.ids.gb._python_access.text = "I Changed It By Clicking!. But That's Not What I Wanted To Program!"
class Change_Label(BoxLayout):
_python_access = ObjectProperty(None)
class OnlyScreen(App):
def build(self):
Clock.schedule_interval(self.Callback_Clock, 3)
return SingleScreen()
def Callback_Clock(self, dt):
print "Hello, world! I'm the clock working...."
# What code goes here that will change the text via Kivy's clock instead of using the button?
if __name__ == '__main__':
OnlyScreen().run()
Please do the following and refer to my example for details:
Snippet
class OnlyScreenApp(App):
def build(self):
Clock.schedule_interval(self.Callback_Clock, 3)
return SingleScreen()
def Callback_Clock(self, dt):
self.root.ids.gb._python_access.text = "I Changed It By Clock! dt=" + str(dt)
Example
main.py
from kivy.app import App
from kivy.uix.boxlayout import BoxLayout
from kivy.clock import Clock
from kivy.properties import ObjectProperty
class SingleScreen(BoxLayout):
pass
class Change_Label(BoxLayout):
_python_access = ObjectProperty(None)
class TestApp(App):
def build(self):
Clock.schedule_interval(self.Callback_Clock, 3)
return SingleScreen()
def Callback_Clock(self, dt):
self.root.ids.gb._python_access.text = "I Changed It By Clock! dt=" + str(dt)
if __name__ == '__main__':
TestApp().run()
test.kv
#:kivy 1.10.0
<SingleScreen>:
id: single_screen
orientation: 'vertical'
Change_Label:
id: gb
<Change_Label>:
_python_access: ChangeLabel
Label:
id: ChangeLabel
text: "I'm Gonna Change."
Output
Based on ikolim's answer above I wanted to post the solution as one complete python program that relates to the format from which the question was posted. Really appreciate the solution. The complete working (one file) code would be as follows;
import kivy
kivy.require('1.9.1')
from kivy.app import App
from kivy.lang import Builder
from kivy.uix.boxlayout import BoxLayout
from kivy.clock import Clock
from kivy.properties import ObjectProperty
Builder.load_string("""
<SingleScreen>:
id: single_screen
orientation: 'vertical'
Change_Label:
id: gb
<Change_Label>:
_python_access: ChangeLabel
Label:
id: ChangeLabel
text: "I'm Gonna Change."
""")
class SingleScreen(BoxLayout):
pass
class Change_Label(BoxLayout):
_python_access = ObjectProperty(None)
class OneScreen(App):
def build(self):
Clock.schedule_interval(self.Callback_Clock, 3)
return SingleScreen()
def Callback_Clock(self, dt):
self.root.ids.gb._python_access.text = "I Changed It By Clock! dt=" + str(dt)
if __name__ == '__main__':
OneScreen().run()

Why do I need to create a new instance of a Line instead of simply update or add and remove it in Kivy

I am attempting to draw a line with the mouse by dragging from one point to another point of the window. I also want to represent the line while I am dragging. Like drawing a line in an old MS PaintBrush.
My problem is that I have only been able to achieve this by constantly removing the old Line and adding a new Vertex Instruction to the canvas. However, I cannot update existing instructions. Not even adding and removing the same instruction. It has to be a new instance of Line. You can see the result that I want by running the following code. If you try to run it with the commented lines it doesn't work any more.
from kivy.app import App
from kivy.uix.relativelayout import RelativeLayout
from kivy.graphics import Line
class MyCanvas(RelativeLayout):
def on_touch_down(self, touch):
with self.canvas:
self.line = Line(points=[touch.x,touch.y,touch.x+1,touch.y+1])
self.bind(on_touch_move=self.update_line, on_touch_up=self.end_line)
return True
def update_line(self, instance, touch):
self.line.points[2] = touch.x
self.line.points[3] = touch.y
self.canvas.remove(self.line)
# self.canvas.add(self.line) # - this doesn't work
# self.canvas.ask_update() # - not even using this
with self.canvas:
self.line = Line(points=self.line.points) # this works
def end_line(self, instance, touch):
self.unbind(on_touch_move=self.update_line)
self.unbind(on_touch_up=self.end_line)
self.line.points[2] = touch.x
self.line.points[3] = touch.y
self.canvas.remove(self.line)
# self.canvas.add(self.line) # - this doesn't work
# self.canvas.ask_update() #- not even using this
self.canvas.add(Line(points=self.line.points)) # this way works
class ExampleApp(App):
def build(self):
return MyCanvas()
ExampleApp().run()
I also tried using Kivy properties as suggested in this other question with the Color instruction. It didn't work and there is another question related to it.
I am struggling with the same problem. I started from the 6_button.py example from the kivy/guide/firstwidget directory
I found something that works (using pop twice to remove the last x,y pair from points) But I think it is very awkward, see my code below. I hope someone can tel us how to 'update' properly.
based on 6_button.py
from random import random
from kivy.app import App
from kivy.uix.widget import Widget
from kivy.uix.button import Button
from kivy.graphics import Color, Ellipse, Line
class MyPaintWidget(Widget):
def on_touch_down(self, touch):
color = (random(), 1, 1)
with self.canvas:
Color(*color, mode='hsv')
d = 10.
Ellipse(pos=(touch.x - d / 2, touch.y - d / 2), size=(d, d))
touch.ud['line'] = Line(points=(touch.x, touch.y, touch.x+30, touch.y))
#print(dir(touch.ud['line']))
def on_touch_move(self, touch):
#touch.ud['line'].points += [touch.x, touch.y]
touch.ud['line'].points.pop() #
touch.ud['line'].points.pop() # works but is awkward
touch.ud['line'].points += [touch.x, touch.y] #
#touch.ud['line'].points[2:4] = [touch.x, touch.y]
#self.canvas.ask_update() # no error but didnt work
#touch.ud['line'].ask_update() # didnt work
#print(touch.ud['line'].points)
#touch.ud['line'].needs_redraw() # error 'bool not callable'
#touch.ud['line'].needs_redraw = True # error 'not writable'
#touch.ud['line'].needs_redraw #no error but doesnt work
class MyPaintApp(App):
def build(self):
parent = Widget()
painter = MyPaintWidget()
clearbtn = Button(text='Clear')
parent.add_widget(painter)
parent.add_widget(clearbtn)
def clear_canvas(obj):
painter.canvas.clear()
clearbtn.bind(on_release=clear_canvas)
return parent
if __name__ == '__main__':
MyPaintApp().run()

on_touch_up event recieved by canvas. Not sure why

Not sure why on_touch_up is being fired when the button is released. The other two events, on_touch_down and on_touch_move are not fired.
from kivy.app import App
from kivy.uix.widget import Widget
from kivy.uix.button import Button
class MyPaintWidget(Widget):
def on_touch_down(self, touch):
print "on_touch_down"
def on_touch_move(self, touch):
print "on_touch_move"
def on_touch_up(self, touch):
print "on_touch_up"
class MyPaintApp(App):
def build(self):
parent = Widget()
painter = MyPaintWidget()
btn = Button(text='Click Me')
parent.add_widget(painter)
parent.add_widget(btn)
return parent
if __name__ == '__main__':
MyPaintApp().run()
You've overloaded the up, down and move methods of MyPainterWidget and they execute as defined when clicking on the widget.
A uix.Button doesn't have a on_touch_up method so the event propagates up the widget tree. You can investigate this a little further by changing the order of
parent.add_widget(painter)
parent.add_widget(btn)
to
parent.add_widget(btn)
parent.add_widget(painter)
We now see that the both "on_touch_up" and "on_touch_down" are printed to the console, even when clicking the uix.Button, rather than just "on_touch_up".
These are facets of how kivy handles events, the details of which can be found here

Resources