Image in canvas with opacity using kivy module - kivy

I can see the effects from the CanvasWidget() class but not any effects from the MyApp() class. Why is it so
#Importing kivy module
import kivy
kivy.require("1.10.1")
from kivy.app import App
from kivy.uix.widget import Widget
from kivy.graphics import Rectangle, Color
from kivy.uix.image import Image
from kivy.config import Config
#Creating the canvas
class CanvasWidget(Widget):
def __init__(self, **kwargs):
super(CanvasWidget, self).__init__(**kwargs)
with self.canvas:
Color(1, 1, 1, 1)
self.rect = Rectangle(pos = self.center, size = (self.width / 2., self.height / 2.))
self.bind(pos = self.update_rect, size = self.update_rect)
def update_rect(self, *args):
self.rect.pos = self.pos
self.rect.size = self.size
class CanvasApp(App):
def build(self):
return CanvasWidget()
CanvasApp().run()
#Putting the image
Config.set("graphics", "resizable", True)
class MyApp(App):
def build(self):
self.img = Image(source = "voithos.jpg")
self.img.allow_stretch = True
self.img.keep_ratio = False
self.img.size_hint_x = 1
self.img.size_hint_y = 1
self.img.pos = (200, 100)
self.img.opacity = 1
s = Widget()
s.add_widget(self.img)
return s
MyApp().run()
This is the output i get

The line:
CanvasApp().run()
will not return until the CanvasApp is shut down. So nothing after that line will be executed until you kill CanvasApp.

Related

How to switch between screens that are .kv files and non-.kv files in Kivy

I am extremely new to kivy (and making apps in general), and I am having trouble switching between screens. I have watched several tutorials, but one of them uses a build method that returns a MDBoxLayout (CameraScreen), and the others use .kv files. I want to be able to switch between the two, or be able to reformat it so that I only use .kv files. Here is my code:
from kivymd.app import MDApp
from kivymd.uix.boxlayout import MDBoxLayout
from kivymd.uix.button import MDRaisedButton
from kivymd.uix.label import MDLabel
from kivy.uix.screenmanager import Screen
from kivy.uix.image import Image
from kivy.lang import Builder
from kivy.graphics.texture import Texture
from kivy.clock import Clock
import cv2
import pytesseract
class HomeScreen(Screen):
pass
class ManageDataScreen(Screen):
pass
class CameraScreen(MDApp):
def build(self):
layout = MDBoxLayout(orientation='vertical')
self.image = Image()
self.label = MDLabel()
layout.add_widget(self.image)
layout.add_widget(self.label)
self.save_img_button = MDRaisedButton(
text="Capture",
pos_hint={'center_x': .5, 'center_y': .5},
size_hint=(None, None))
self.save_img_button.bind(on_press=self.take_picture)
layout.add_widget(self.save_img_button)
self.capture = cv2.VideoCapture(0)
Clock.schedule_interval(self.load_video, 1.0/30.0)
return layout
def load_video(self, *args):
ret, frame = self.capture.read()
# Frame initialize
self.image_frame = frame
buffer = cv2.flip(frame, 0).tostring()
texture = Texture.create(size=(frame.shape[1], frame.shape[0]), colorfmt='bgr')
texture.blit_buffer(buffer, colorfmt='bgr', bufferfmt='ubyte')
self.image.texture = texture
def take_picture(self, *args):
image_name = "img_TIMESTAMP.png"
img = cv2.cvtColor(self.image_frame, cv2.COLOR_BGR2GRAY)
img = cv2.GaussianBlur(img, (3, 3), 0)
img = cv2.threshold(img, 0, 255, cv2.THRESH_BINARY_INV + cv2.THRESH_OTSU)[1]
text_data = pytesseract.image_to_string(img, lang='eng', config="--psm 6")
self.label.text = text_data
cv2.imshow("cv2 final image", img)
cv2.imwrite(image_name, self.image_frame)
GUI = Builder.load_file("kv/main.kv")
class MainApp(MDApp):
def build(self):
return GUI
def change_screen(self, screen_name):
screen_manager = self.root.ids['screen_manager']
if screen_name == "camera_screen":
CameraScreen().run()
else:
screen_manager.current = screen_name
if __name__ == '__main__':
pytesseract.pytesseract.tesseract_cmd = r"C:\Program Files\Tesseract-OCR\tesseract.exe"
MainApp().run()
and here is my main.kv file
#:include kv/home_screen.kv
#:include kv/manage_data_screen.kv
GridLayout:
cols: 1
ScreenManager:
id: screen_manager
HomeScreen:
name: "home_screen"
id: home_screen
ManageDataScreen:
name: "manage_data_screen"
id: manage_data_screen

KIVY DragBehavior Custom Widget

I am trying to use DragBehavior to help in moving my custom widget across RelativeLayout. Find below sample code. Why my widget is not moving on Drag action please. For simplicity I had included only rectangle in my custom widget MyPaintWidget
from kivy.app import App
from kivy.graphics import Line
from kivy.uix.scatter import Scatter
from kivy.uix.relativelayout import RelativeLayout
from kivy.uix.behaviors import DragBehavior
from kivy.lang import Builder
from kivy.graphics import Color, Rectangle
Builder.load_string("""
<MyPaintWidget>:
# Define the properties for the DragLabel
drag_rectangle: self.x, self.y, self.width, self.height
drag_timeout: 10000000
drag_distance: 0
""")
class MyPaintWidget(DragBehavior, Scatter):
def __init__(self, **kwargs) :
self.selected = None
self.touched = False
super(MyPaintWidget, self).__init__(**kwargs)
def create_figure(self, **kwargs):
print ('position is {}'.format(self.pos))
print ('width Height {}'.format(self.to_parent(self.width, self.height)))
self.canvas.add(Rectangle(pos = self.pos, size = self.size))
return self
def on_touch_move(self, touch):
print('Started to move x: {} y: {}'.format(touch.x, touch.y))
return super(MyPaintWidget, self).on_touch_move(touch)
class MyPaintApp(App):
def build(self):
parent = RelativeLayout()
self.painter = MyPaintWidget(pos_hint={"center_x": 0.5, 'center_y':0.5}, size_hint=(.2,.1))
parent.add_widget(self.painter.create_figure())
return parent
if __name__ == '__main__':
MyPaintApp().run()
The DragBehavior works by adjusting the pos of your MyPaintWidget, but you have set pos_hint on the MyPaintWidget. The pos_hint takes precedence over pos, so while the drag changes pos, it is ignored because there is a pos_hint. Also, the Rectangle that you draw in create_figure has its size and pos set when that method is called, and there is no mechanism to change it when the MyPaintWidget is moved. So, even if the Widget was being dragged, the Rectangle would not move.
Here is a version of your code with those problems corrected:
from kivy.app import App
from kivy.uix.scatter import Scatter
from kivy.uix.relativelayout import RelativeLayout
from kivy.uix.behaviors import DragBehavior
from kivy.lang import Builder
Builder.load_string("""
<MyPaintWidget>:
# Define the properties for the DragLabel
drag_rectangle: self.x, self.y, self.width, self.height
drag_timeout: 10000000
drag_distance: 0
canvas:
Color:
rgba: 1,0,0,1
Rectangle:
pos: 0,0 # only do this for RelativeLayout
size: self.size
""")
class MyPaintWidget(DragBehavior, Scatter):
def __init__(self, **kwargs) :
self.selected = None
self.touched = False
super(MyPaintWidget, self).__init__(**kwargs)
def on_touch_move(self, touch):
print('Started to move x: {} y: {}'.format(touch.x, touch.y))
return super(MyPaintWidget, self).on_touch_move(touch)
class MyPaintApp(App):
def build(self):
parent = RelativeLayout()
self.painter = MyPaintWidget( pos=(240, 200), size_hint=(.2,.1))
parent.add_widget(self.painter)
return parent
if __name__ == '__main__':
MyPaintApp().run()

KIVY : Scroll Bar missing

I am trying my hands on ScrollView within anchorlayout. Unable to get scroll bar in Relativelayout. Please find below my sample code. Why scrollbar is not visible.
import kivy
from kivy.app import App
from kivy.uix.scrollview import ScrollView
from kivy.lang import Builder
from kivy.uix.relativelayout import RelativeLayout
from kivy.uix.button import Button
from kivy.factory import Factory
from kivy.core.window import Window
Builder.load_string('''
<ScrollView>:
size_hint: 1,1
DrawingSpace:
size_hint: 1,1
''')
class Main(App):
def build(self):
self.root=DrawingSpace()
return self.root
class DrawingSpace(RelativeLayout):
def __init__(self, **kwargs):
super(RelativeLayout, self).__init__(**kwargs)
self.add_widget( Button(text = 'Scroll', size_hint=(None,None), size=(50,200), pos = (100, 100)))
self.add_widget( Button(text = 'Scroll', size_hint=(None,None), size=(50,200), pos = (250, 300)))
Factory.register('DrawingSpace', cls=DrawingSpace)
if __name__ in ('__main__'):
Window.size = (200, 200)
app = Main()
app.run()
Thanks
For ScrollView, in the direction you want scrolling, you have to set size_hint to None and specify the size. I used 500 for testing.
import kivy
from kivy.app import App
from kivy.uix.scrollview import ScrollView
from kivy.lang import Builder
from kivy.uix.relativelayout import RelativeLayout
from kivy.uix.button import Button
from kivy.factory import Factory
from kivy.core.window import Window
Builder.load_string('''
<ScrollView>:
size_hint: 1,1
DrawingSpace:
size_hint: 1,None
height: 500
''')
class Main(App):
def build(self):
self.root=ScrollView()
return self.root
class DrawingSpace(RelativeLayout):
def __init__(self, **kwargs):
super(RelativeLayout, self).__init__(**kwargs)
self.add_widget( Button(text = 'Scroll', size_hint=(None,None), size=(50,200), pos = (100, 100)))
self.add_widget( Button(text = 'Scroll', size_hint=(None,None), size=(50,200), pos = (250, 300)))
Factory.register('DrawingSpace', cls=DrawingSpace)
if __name__ in ('__main__'):
Window.size = (200, 200)
app = Main()
app.run()

Kivy: Drawing to widget

I collect experiencies with kivy and I have problem with using widget center. My problem shows next script:
from kivy.uix.button import Button
from kivy.uix.widget import Widget
from kivy.uix.boxlayout import BoxLayout
from kivy.app import App
from functools import partial
from kivy.graphics import Color, Ellipse
class CanvasApp(App):
def draw(self,wid, color):
with wid.canvas:
Color(color[0], color[1], color[2])
Ellipse(size= (100, 100), pos=(wid.center_x, wid.center_y))
return
def painter(self, wid, *largs):
self.draw(wid, (0, 1, 0))
return
def build(self):
wid = Widget()
btn_painter = Button(text='Painter',
on_press=partial(self.painter, wid))
ctrl = BoxLayout(size_hint=(1, None), height=50)
ctrl.add_widget(btn_painter)
root = BoxLayout(orientation='vertical')
root.add_widget(wid)
root.add_widget(ctrl)
self.draw(wid, (1, 0, 0))
return root
if __name__ == '__main__':
CanvasApp().run()
I want to draw circle in the widget center (black rectangle) without using button painter. I don't able obtain actually center coordinates of center. Without using button are available only default center coordinates. How is OK process?
Thank you for answers.
The problem is that the wid size and position are not yet set inside the build() method. So you need to delay the call of draw() a bit. Try replacing the call to draw() with:
Clock.schedule_once(partial(self.draw, wid, (1,0,0)))
You will also need to change the draw() method slightly to handle the dt argument that gets added:
def draw(self,wid, color, *args):
I found solution of my problem. All explains follow script:
from kivy.app import App
from kivy.graphics import Color, Rectangle, Ellipse
from kivy.uix.floatlayout import FloatLayout
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.button import Button
class DrawArea(FloatLayout):
def __init__(self, **kwargs):
# make sure we aren't overriding any important functionality
super(DrawArea, self).__init__(**kwargs)
self.rect1 = None
self.li_item = []
return
def clear_area(self):
for item in self.li_item:
self.canvas.remove(item)
self.li_item.clear()
def draw_rect(self):
with self.canvas:
Color(0, 1, 0, 1) # green; colors range from 0-1 not 0-255
self.rect1 = Rectangle(size=self.size, pos=self.pos)
Color(1, 0, 0, 1) # green; colors range from 0-1 not 0-255
width = self.width/2
height = self.height/2
pos_x = self.center_x -width/2
pos_y = self.center_y - height/2
self.rect2 = Rectangle(size=(width, height), pos=(pos_x, pos_y))
self.li_item.append(self.rect1)
self.li_item.append(self.rect2)
return
def draw_circle(self):
Color(1, 0, 0)
d = 120
with self.canvas:
Color(0, 1, 0)
self.circle1 = Ellipse(size = (d,d), pos = (self.center_x-d/2, self.center_y-d/2))
Color(0, 0, 1)
self.circle2 = Ellipse(size = (d/2,d/2), pos = (self.center_x - self.size[0]/2, self.center_y - self.size[1]/2))
self.li_item.append(self.circle1)
self.li_item.append(self.circle2)
return
class MainApp(App):
def build(self):
self.task = 'circle'
root = BoxLayout(orientation = 'vertical')
self.dra = DrawArea()
button = Button(text = 'painter',size_hint=(1, None), height=50, on_press = self.but_paint)
root.add_widget(self.dra)
root.add_widget(button)
if self.task == 'circle':
self.dra.bind(pos = self._update_circ, size = self._update_circ)
self.dra.draw_circle()
else:
self.dra.bind(size=self._update_rect, pos=self._update_rect)
self.dra.draw_rect()
return root
def but_paint(self, instance):
#self.dra.clear_area()
if self.task == 'circle':
self.task = 'rectangle'
else:
self.task = 'circle'
if self.task == 'circle':
self.dra.bind(pos = self._update_circ, size = self._update_circ)
self.dra.draw_circle()
else:
self.dra.bind(size=self._update_rect, pos=self._update_rect)
self.dra.draw_rect()
return
def _update_circ(self, instance, value):
d = 120
pos1_x = instance.center[0] -d/2
pos1_y = instance.center[1] -d/2
self.dra.circle1.pos = (pos1_x, pos1_y)
pos2_x = instance.center[0] - instance.size[0]/2
pos2_y = instance.center[1] - instance.size[1]/2
self.dra.circle2.pos = (pos2_x, pos2_y)
return
def _update_rect(self, instance, value):
if self.dra.rect1 != None:
self.dra.rect1.pos = instance.pos
self.dra.rect1.size = instance.size
width = instance.size[0]/2
height = instance.size[1]/2
pos_x = instance.center[0] -width/2
pos_y = instance.center[1] - height/2
self.dra.rect2.pos = (pos_x, pos_y)
self.dra.rect2.size = (width, height)
def draw_rect(self):
with self.dra.canvas.before:
Color(0, 1, 0, 1) # green; colors range from 0-1 not 0-255
self.rect1 = Rectangle(size=self.dra.size, pos=self.dra.pos)
Color(1, 0, 0, 1) # green; colors range from 0-1 not 0-255
width = self.width/2
height = self.height/2
self.rect2 = Rectangle(size=(width, height), pos=(self.center_x -width/2, self.center_y - height/2))
return
if __name__ == '__main__':
MainApp().run()

Increase the linewidth of a MeshLinePlot in Kivy?

Does anyone know how to increase the linewidth of a MeshLinePlot in Kivy?
Thank you
Update
I got the answer from #Ikolim to work modifying the LinePLot function from kivy.graph
class LinePlot(Plot):
'''LinePlot draws using a standard Line object.
'''
'''Args:
line_width (float) - the width of the graph line
'''
def __init__(self, line_width=1, **kwargs):
self._line_width = line_width # instead of kwargs.get('line_width', 1)
super(LinePlot, self).__init__(**kwargs)
Base on the method __init__ for Kivy garden.graph at https://github.com/kivy-garden/garden.graph/blob/master/init.py, MeshLinePlot currently does not support line width. But LinePlot do support line width.
snippet
self.plot = LinePlot(line_width=4, color=[1, 0, 0, 1])
Example
main.py
import kivy
kivy.require("1.10.0")
from kivy.app import App
from kivy.lang import Builder
from kivy.uix.boxlayout import BoxLayout
from kivy.garden.graph import Graph, MeshLinePlot, MeshStemPlot, LinePlot, SmoothLinePlot, ContourPlot
import matplotlib.pyplot as plt
from kivy.garden.matplotlib.backend_kivyagg import FigureCanvas
from kivy.utils import get_color_from_hex as rgb
from numpy import sin
kv = """
<GraphCustom>:
<Test>:
orientation: 'vertical'
GraphCustom:
size: self.parent.size
pos: self.parent.pos
"""
Builder.load_string(kv)
class GraphCustom(Graph):
def __init__(self, **kwargs):
super(GraphCustom, self).__init__(**kwargs)
self.label_options = {'color': rgb('#FF0000'), 'bold': True}
self.background_color = rgb('f8f8f2')
self.tick_color = rgb('808080')
self.border_color = rgb('808080')
self.xlabel = 'X'
self.ylabel = 'Y'
self.x_ticks_minor = 5
self.x_ticks_major = 25
self.y_ticks_major = 1
self.y_grid_label = True
self.x_grid_label = True
self.padding = 5
self.x_grid = True
self.y_grid = True
self.xmin = -0
self.xmax = 100
self.ymin = -1
self.ymax = 1
self.stop = False
self.plot = LinePlot(line_width=4, color=[1, 0, 0, 1])
self.plot.points = [(x, sin(x / 10.)) for x in range(0, 101)]
self.add_plot(self.plot)
class Test(BoxLayout):
def __init__(self, *args, **kwargs):
super(Test, self).__init__(*args, **kwargs)
fig1 = plt.figure()
ax1 = fig1.add_subplot(111)
wid = FigureCanvas(fig1)
self.add_widget(wid)
class TestApp(App):
title = "Kivy Garden Graph - LinePlot Demo"
def build(self):
return Test()
if __name__ == '__main__':
TestApp().run()
Output

Resources