This is the code:
from kivy.app import App
from kivy.uix.widget import Widget
from kivy.graphics import Color
from kivy.graphics import Line
class MainWidget(Widget):
v_l_s=.1
v_l_n=7
Vertical_lines=[]
def __init__(self,**kwargs):
super().__init__(**kwargs)
self.init_vertical_lines()
def on_size(self,*args):
self.update_vertical_lines()
def init_vertical_lines(self):
for num in range(0,self.v_l_n):
self.Vertical_lines.append(Line())
def update_vertical_lines(self):
cener_x=int(self.width/2)
before_lines=-(int(self.width/2))
line_x=cener_x+before_lines*self.v_l_s
for numb in range(0,self.v_l_n):
with self.canvas:
self.Vertical_lines[numb].points=[line_x,0,line_x,self.height]
before_lines+=1
class GameApp(App):
def build(self):
return MainWidget()
GameApp().run()
This code should return 7 vertical lines but it is showing nothing. What should I do to solve it ?(Note-An error is coming in publishing the question so don't care about this Note)
When you initially create the Line() instance, you are not doing in a canvas context. Just add with self.canvas: to the init_vertical_lines() method:
def init_vertical_lines(self):
with self.canvas:
for num in range(0, self.v_l_n):
self.Vertical_lines.append(Line())
Your code will then draw the 7 lines, but they are all in the same place (that's a different issue).
Related
As you all know kivy Line take points with (x1,y1.x2,y2,x3,y3). I want to create a geometric compass like it is in here. Considering the compass here I created a basic framework of this, which doesn't seems to be good enough.. (though isn't even close to match the compass there but is just the basic idea)
import kivy
from kivy.uix.widget import Widget
from kivy.uix.widget import Canvas
from kivy.graphics import Color
from kivy.graphics import Line
from kivy.uix.floatlayout import FloatLayout
from kivymd.app import MDApp
from kivy.uix.button import Button
from kivymd.uix.card import MDCard
class Main(FloatLayout):
def __init__(self,**kwargs):
super(Main, self).__init__(**kwargs)
self.my_widget = Widget(size_hint= (0.6,0.6),pos_hint = {'x':0.5,'top' : 0.8})
self.add_widget(self.my_widget)
with self.my_widget.canvas:
Color(rgba = (0,0,0,1))
def on_touch_downah(self,touch):
self.line = Line(points = (touch.x,touch.y),width = 4)
self.canvas.add(self.line)
def on_touch_moveah(self,touch):
self.line.points += touch.x,touch.y
self.my_widget.bind(on_touch_down=on_touch_downah)
self.my_widget.bind(on_touch_move=on_touch_moveah)
def on_touch_downeh(self, touch):
self.x_ = touch.x
self.y_ = touch.y
self.lines = Line(points=(touch.x,touch.y),width = 5)
self.canvas.add(self.lines)
def on_touch_moveeh(self, touch):
self.x2 = self.x_ + 0.1
self.y2 = self.y_ + 0.1
self.lines.points = (self.x_,self.y_,touch.x,touch.y,touch.x,touch.y)
self.my_widget.bind(on_touch_down=on_touch_downeh)
self.my_widget.bind(on_touch_move=on_touch_moveeh)
class Mysapp(MDApp):
def build(self):
return Main()
Mysapp().run()
It is just a framework but the only problem here is the length of the straight _line is not getting fixed, meaning it keep changing because of x3,y3. Is there any way to fix the length of this line so that under no circumstances its length would get modified but it should still be able to change its position?
Or is there any better widget for this purpose other than the circle widget? I want the user to be able to create curves and arcs as well as circles therefore can't switch to circle widget. The user should be able to use it just as the geometric compass as you can see the provided link..
I have put the video inside kivy canvas, first 3 sec showing image afterthat will be play video. But only show all time image only.
Any suggestion.
Thanks
import kivy
from kivymd.app import MDApp
from kivy.uix.widget import Widget
from kivy.graphics import Rectangle ,Color
from kivy.core.video import Video as CoreVideo
from kivy.clock import Clock
class Mycanvas(Widget):
def __init__(self,**kw):
super(Mycanvas,self).__init__(**kw)
with self.canvas:
self.bg = Rectangle(source='Flower.jpg', pos=self.pos, size=self.size)
self.video = CoreVideo()
self.video.bind(on_frame=self.set_bg_texture)
self.video.filename = 'Garden.mp4'
Clock.schedule_once(self.start_vid, 3)
self.start_vid(3)
def start_vid(self, dt):
self.video.play()
def set_bg_texture(self, *args):
self.bg.texture = self.video.texture
class mainapp(MDApp):
def build(self):
return Mycanvas()
mainapp().run()
Hello i'm relatively new to python and kivy and I've been looking around but i cant quite find the answer, i'm trying to make a hub where I can display live data from my rasberry-pi. I made a clock widget using a Label, and it updates time, but when i try to add my CPU usage only one label shows up. I thought the widgets might be covering each other but I used size_hint and it wont help. When i run the code below, only the timex will show up and only if i delete the Clock.schedule_interval(display32.timex, (1)) will the *updatex * display.
Thanks alot for the help
from kivy.app import App
from kivy.uix.label import Label
from kivy.clock import Clock
from kivy.uix.floatlayout import FloatLayout
import psutil
from kivy.lang import Builder
import time
class Display(Label, FloatLayout):
def __init__(self):
super(Display, self).__init__()
def updatex(self, *args):
self.cpu2 = psutil.cpu_percent()
self.text=str(self.cpu2)
self.size_hint=(.5, .25)
self.pos=(500, 500)
self.texture_size=(0.1,0.1)
def timex(self, *args):
self.time2 = time.asctime()
self.text = str(self.time2)
self.size_hint = (.5, .25)
self.pos = (30, 500)
self.size_hint=(0.1,0.1)
class TimeApp(App):
def build(self):
display32 = Display()
Clock.schedule_interval(display32.updatex, (1))
Clock.schedule_interval(display32.timex, (1))
return display32
if __name__ == "__main__":
TimeApp().run()
Instead of passing both labels to the clock, you can define a widget, add both labels and start the clock on the widget.
from kivy.app import App
from kivy.uix.widget import Widget
from kivy.uix.label import Label
from kivy.clock import Clock
import psutil
import time
class Display(Widget):
def draw(self, *args):
self.clear_widgets()
self.add_widget(Label(text=str(psutil.cpu_percent()), pos=(500, 500)))
self.add_widget(Label(text=str(time.asctime()), pos=(30, 500)))
class TimeApp(App):
def build(self):
display32 = Display()
Clock.schedule_interval(display32.draw, 1)
return display32
if __name__ == '__main__':
TimeApp().run()
I am trying update Label on canvas , but it changed only if I call update() method from MyApp(APP).
And what is interesting that method obj Slider (on touch) works perfectly
from kivy.app import App
from kivy.uix.widget import Widget
from kivy.core.window import Window
from kivy.uix.label import Label
from kivy.uix.floatlayout import FloatLayout
from kivy.uix.gridlayout import GridLayout
from kivy.uix.boxlayout import BoxLayout
from kivy.graphics import (Color, Ellipse)
from kivy.uix.slider import Slider
import random
from functools import partial
class Canvas_w(Widget):
def __init__(self, **kwargs):
self.i = 0
super(Canvas_w, self).__init__(**kwargs)
self.label_text =Label(text= "0",color = (255,0,0))
def update_text(self, text):
self.label_text.text = text
def on_touch_down(self, touch):
with self.canvas:
d=30
self.i+=1
Color(1., 0, 0)
Ellipse(pos=(touch.x - d/2, touch.y - d/2), size=(20,20))
self.label_text=str(self.i)
class Label_l(GridLayout):
bones = 0
def __init__(self, **kwargs):
super(Label_l, self).__init__(**kwargs)
self.label_text =Label(text= "0")
self.add_widget(self.label_text)
#self.label_text.text=self.C.i
def update_text(self, text):
Label_l.bones=text
self.label_text.text = str(Label_l().bones)#
Label_l.text=str(Label_l().bones)
class WidgetContainer(GridLayout):
sld_value = 0.00001
def __init__(self, **kwargs):
super(WidgetContainer, self).__init__(**kwargs)
self.cols = 1
self.speedControl = Slider(min=0.00001, max=3, step=0.0001)
self.add_widget(Label(text="Speed Iteration"))
self.add_widget(self.speedControl)
self.add_widget(Label(text=''))
self.speedValue = Label(text="0.00001")
self.add_widget(self.speedValue)
self.speedControl.bind(value=self.on_value)
def on_value(self, instance, speed):
self.sld_value = speed
WidgetContainer.sld_value = self.sld_value
self.speedValue.text = str(round(speed,5))
class MyApp(App):
def build(self):
b3 = BoxLayout(orientation="horizontal")
b1 = FloatLayout()
self.painter = Canvas_w()
self.label_l= Label_l()
b1.add_widget(self.label_l)
b1.add_widget(self.painter)
b1.add_widget(WidgetContainer())
b3.add_widget(b1)
return(b3)
if __name__=="__main__":
MyApp().run()
I am trying update Label on canvas , but it changed only if I call update() method from MyApp(APP).
And what is interesting that method obj Slider (on touch) works perfectly
A few problems with your code:
The color attribute of a Label requires a list of four values with each value in the range 0 to 1. Change self.label_text =Label(text= "0",color = (255,0,0)) to self.label_text =Label(text= "0",color = (1,0,0,1)) in the Canvas_w class.
The above Label is never getting drawn. You need to add self.add_widget(self.label_text) to the __init__() method of Canvas_w.
You have another Label in the Label_l class that is being drawn on top of the Label in the Canvas_w.
After fixing the above problems, I believe your code will work as you expect.
If you call self.canvas.clear(), it appears as though the label_text child of Canvas_w is removed. Actually it is not removed, but is just not visible (perhaps overdrawn). One way to make it visible is to just make sure it is drawn last by removing it and then re-adding it (last added child is drawn last), like this:
self.canvas.clear()
self.remove_widget(self.label_text)
self.add_widget(self.label_text)
After a bit more research, I believe that the canvas.clear() is removing the drawing of the Label from the Canvas. You can, however, do your drawing on canvas.before by using:
with self.canvas.before:
in the on_touch_down() method. And rather than using:
self.canvas.clear()
use:
self.canvas.before.clear()
I believe that your Label will be displayed correctly after doing the above.
I'm not really sure as to why the canvas isn't clearing.
The first build(self) implementation that has the parent variable is the one that works. The only thing I see different is that the second implementation is adding the Button widget to the MyPaintWidget instead of both of those widgets getting added to a default Widget class.
Very new to kivy i'm semi-familiar with python. I'd love an explanation.
from random import random
import kivy
kivy.require('1.9.1')
from kivy.app import App
from kivy.uix.button import Button
from kivy.uix.widget import Widget
from kivy.uix.label import Label
from kivy.uix.textinput import TextInput
from kivy.uix.gridlayout import GridLayout
from kivy.graphics import Color, Ellipse, Line
'''
class LoginScreen(GridLayout):
def __init__(self, **kwargs):
super(LoginScreen, self).__init__(**kwargs)
self.cols=2
self.add_widget(Label(text='User Name'))
self.username=TextInput(multiline=False)a
self.add_widget(self.username)
self.add_widget(Label(text='password'))
self.password=TextInput(password=True, multiline=False)
self.add_widget(self.password)
class MainApp(App):
def build(self):
return LoginScreen()
'''
class MyPaintWidget(Widget):
def on_touch_down(self, touch):
color = (random(), 1, 1)
with self.canvas:
Color(*color)
d = 30.
Ellipse(pos=(touch.x - d / 2, touch.y - d / 2), size=(d, d))
touch.ud['line'] = Line(points=(touch.x, touch.y))
print(touch)
def on_touch_move(self, touch):
touch.ud['line'].points += [touch.x, touch.y]
class MyPaintApp(App):
#WHY ARE THESE TWO IMPLEMENTATIONS OF BUILD SO DIFFERENT?????
'''
def build(self):
parent = Widget()
self.painter = MyPaintWidget()
clearbtn = Button(text='Clear')
clearbtn.bind(on_release=self.clear_canvas)
parent.add_widget(self.painter)
parent.add_widget(clearbtn)
return parent
'''
def build(self):
self.painter = MyPaintWidget()
clearbtn = Button(text='Clear')
clearbtn.bind(on_release=self.clear_canvas)
self.painter.add_widget(clearbtn)
return self.painter
def clear_canvas(self, obj):
self.painter.canvas.clear()
if __name__ == '__main__':
MyPaintApp().run()
Touches are dispatched down the widget tree, they enter at the root widget which must pass the touch down to its children (or fail to do so, if it wants).
Your MyPaintWidget class overrides on_touch_down but fails to pass the touch to its children, so the Button never receives the touch and never gets a chance to become pressed.
Add return super(MyPaintWidget, self).on_touch_down(touch) to the MyPaintWidget.on_touch_down to call the parent class method that automatically handles this for you.