I am having issues automatically updating my figures on Kivy after I have updated the two JPG files that contain the image data.
In my minimal/sample code, I want the images to switch if self.count
is '1' or '0'.
Here is my sample code:
#!/usr/bin/env python
"""Client specifically for presentations
This client is meant to run on a computer withouth ROS
"""
import kivy
kivy.require('1.8.0')
#import StringIO
from kivy.uix.floatlayout import FloatLayout
from kivy.app import App
from kivy.graphics import Rectangle
from kivy.clock import Clock
from kivy.logger import Logger
from kivy.core.image import Image
from kivy.uix.widget import Widget
from kivy.uix.label import Label
from kivy.config import Config
from kivy.cache import Cache
Cache.remove('kv.image')
Cache.remove('kv.texture')
#Config.set('graphics', 'fullscreen', 1)
# screen resolution is 1366x768 for the Asus computer
Config.set('graphics', 'width', '1366')
Config.set('graphics', 'height', '768')
#import pprint
import xml.etree.ElementTree as ET
import base64
# FIXME this shouldn't be necessary
from kivy.base import EventLoop
EventLoop.ensure_window()
STORE_SUBPROCESS = [] # stores roscore and rover program
class ControlClass(FloatLayout):
"""Class grabs data form
"""
def __init__(self, **kwargs):
"""
We use __init__ because some variables cannot be initialized
to an ObjectProperty for some reason, so we gotta initialize
it this way
"""
super(ControlClass, self).__init__(**kwargs)
self._started = False # true if client connected
self.proxy = None
self.res_x = 1366
self.res_y = 716
# normal image widget
self.norm_im_widget = Widget()
# self.norm_im_widget.pos = self.pos
# self.norm_im_widget.size = self.size
self.add_widget(self.norm_im_widget)
self.count = 1
# ++++++++++++Real Time Data+++++++++++++++++++++++
self.alpr_page = Image('ALPR Page.jpg').texture
self.alrp_info_coming = False
self.background_size = (2880, 1800)
# initialize connection to robot
self.show_alpr_image()
self.schedule_alpr_display()
def get_image_size(self, size, height):
"""Outputs correct image size on screen
Assume all images are 2880 x 1800 for now
"""
home_size = size #(2880, 1800)
# calculate new image size
aspect_ratio = float(home_size[1]) / float(home_size[0])
h = height # self.height
w = float(h) / float(aspect_ratio) # desired height
size = (w, h)
position = (self.center_x - w/2, self.center_y - h/2)
return (position, size)
def show_alpr_image(self):
"""Display the normal image comming straight from the alpr
"""
# convert data to store in .jpg file
try:
im_res = (437, 77) # image original resolution
plate_size = self.get_image_size(im_res, 65 )
im_res = (352, 240)
car_size = self.get_image_size(im_res, 300 )
# # image's origin starts from buttom left
x_shift = self.res_x - self.res_x*.4
y_shift = self.res_y - self.res_y*0.7905
(plate_x, plate_y) = (self.center_x + x_shift,
self.center_y/7 + y_shift - 90)
(car_x1, car_y1) = (self.center_x + x_shift - 40,
self.center_y/2.5 + y_shift)
Cache.remove('kv.image')
Cache.remove('kv.texture')
self.remove_widget(self.norm_im_widget)
self.add_widget(self.norm_im_widget)
# self.norm_im_widget.canvas.clear()
if self.count == 1:
self.count = 0
print('car')
with self.norm_im_widget.canvas: #display image
Rectangle(source = 'plate.jpg', pos= (plate_x, plate_y),
size=plate_size[1])
Rectangle(source = 'car.jpg', pos= (car_x1, car_y1),
size=car_size[1])
else:
print('plate')
self.count = 1
with self.norm_im_widget.canvas: #display image
Rectangle(source = 'plate.jpg', pos= (plate_x, plate_y),
size=plate_size[1])
Rectangle(source = 'plate.jpg', pos= (car_x1, car_y1),
size=car_size[1])
except BaseException as e:
Logger.warning('Error getting image frame %s'%e)
pass
# self.stop_connection()
def get_alpr_data(self, dt):
# get image data from most recent license plate
self.show_alpr_image()
def schedule_alpr_display(self, *args):
"""calls the replay_videos function on loop"""
Clock.schedule_interval(self.get_alpr_data, 1.0 / 2.0)
########## Connect to robot ###############################
############################################################
class KivyGui(App):
try:
def build(self):
return ControlClass()
except BaseException:
from sys import exit
exit()
if __name__ == '__main__':
KivyGui().run()
And here is my kv file:
#:kivy 1.0
#:import kivy kivy
#:import win kivy.core.window
#:kivy 1.8.0
#
# To load this file, Kivy looks if there is a Kv file with
# the same name as your App class in lowercase, minus
# "App" if it ends with "App". E.g: KivyRobot -> kivy.kv
<ControlClass, FloatLayout>:
cols: 4
row: 4
canvas.before:
Rectangle:
# background image
source: 'ALPR Page.jpg'
pos: self.pos
size: self.size
I am not sure why this does not work and I don't know what else to do.
Feel free to use other sample images, since you don't have the files I have.