I am trying to update the image source on a changeImageSource function it changes the source instantly but when I use time.sleep() method in that function, function executes but doesn't update the source of the image. updates after time.sleep() call completed.
from kivy.app import App
from kivy.uix.image import AsyncImage
from kivy.uix.button import Button
from kivy.uix.widget import Widget
import time
# creating the App class
class MyApp(App):
def build(self):
parent = Widget()
#creating and adding image to widget
self.img = AsyncImage(
source='http://kivy.org/logos/kivy-logo-black-64.png')
self.img.pos = (400,400)
#creating btn and adding press handler
self.change_img_btn = Button(text="Change Image ")
self.change_img_btn.bind(on_press = self.changeImageSource)
#adding widget to Widget instance
parent.add_widget(self.img)
parent.add_widget(self.change_img_btn)
return parent;
def changeImageSource(self,*args):
self.img.source = "https://cdn.sstatic.net/Sites/stackoverflow/Img/apple-touch-icon.png?v=c78bd457575a"
time.sleep(4)
# run the App
MyApp().run()
One: The "return parent;" should be "return parent"
Two: Why do you need time.sleep()?
You can also try flipping line 29 and 30.
Related
I am a new learner of the Kivy module.I am practicing making a selfie app by following a video, by clicking on the button, the camera takes a frame and export it as a PNG image. in code I am adding widget (camera, button), and what show is a black screen. so what should I do?
import cv2
from kivy.app import App
from kivy.uix.camera import Camera
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.button import Button
class selfie_app(App):
def make(self):
self.obj_camera = Camera()
self.obj_camera.resolution = (810, 810)
obj_button = Button(text="Click !!")
obj_button.size_hint = (.5,.2)
obj_button.pos_hint = {'x':.15, 'y':.15}
obj_button.bind(on_press = self.selfie_take())
obj_layout = BoxLayout()
obj_layout.add_widget(obj_button)
obj_layout.add_widget(self.obj_camera)
return obj_layout
def selfie_take(self, *args):
print("selfie taken successfully !")
self.obj_camera.export_to_png('./demo_file.png')
if __name__ == '__main__':
selfie_app().run()
Basically I have this code:
import time
from kivy.app import App
from kivy.uix.camera import Camera
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.button import Button
class MainWindow(App):
def build(self):
layout = BoxLayout(orientation='vertical')
# Create a camera object
self.cameraObject = Camera(play=False)
self.cameraObject.play = True
self.cameraObject.resolution = (300, 300) # Specify the resolution
# add camera and button to the layout
layout.add_widget(self.cameraObject)
# return the root widget
return layout
# Take the current frame of the video as the photo graph
def onCameraClick(self, *args):
self.cameraObject.export_to_png('hello.png')
print("Success")
if __name__ == '__main__':
MainWindow().run()
while True:
time.sleep(1)
MainWindow().onCameraClick()
What it's supposed to do is:
Run the window
Show the webcam in window
Repeatedly take pictures using the webcam and save it as hello.png
What's it's doing:
Run the window
Show the webcam in window
What's wrong with my code? Is it something to do with trying to access a function inside another class? Or is it an argument error? If it is, I don't see any errors in the log messages.
The problem is that you are trying to save the images after the MainWindow().run(), which does not return until the App is stopped. Try modifying your build() method to use Clock.schedule_interval to save the images:
def build(self):
layout = BoxLayout(orientation='vertical')
# Create a camera object
self.cameraObject = Camera(play=False)
self.cameraObject.play = True
self.cameraObject.resolution = (300, 300) # Specify the resolution
# add camera and button to the layout
layout.add_widget(self.cameraObject)
# save some images
Clock.schedule_interval(self.onCameraClick, 2)
# return the root widget
return layout
try using the same window
if __name__ == '__main__':
win = MainWindow()
win.run()
while True:
time.sleep(1)
win.onCameraClick()
I'm working on an app, and I need the images to display independently at a specific timing. I have set up a thread using python's stock threading module, it runs and works normally instead of the image it displays a black square. Does anyone know how to fix it?
Here is my code to reproduce the issue:
import threading
from kivy.app import App
from kivy.uix.image import Image
from kivy.uix.button import Button
from kivy.uix.floatlayout import FloatLayout
class TestApp(App):
def build(self):
self.fl = FloatLayout()
self.fl.add_widget(Button(text="show image", on_press=self.start_thread))
return self.fl
def insertfunc(self):
self.fl.add_widget(Image(source="HeartIcon.png"))
def start_thread(self, instance):
threading.Thread(target=self.insertfunc).start()
TestApp().run()
Any help will be appreciated!
The add_widget() must be done on the main thread. I assume that you are using threading because you have additional things to do on the Thread aside from just the add_widget(). Based on that assumption, here is a modified version of your code that does what I think you want:
import threading
from kivy.app import App
from kivy.clock import Clock
from kivy.uix.image import Image
from kivy.uix.button import Button
from kivy.uix.floatlayout import FloatLayout
class TestApp(App):
def build(self):
self.fl = FloatLayout()
self.fl.add_widget(Button(text="show image", on_press=self.start_thread))
return self.fl
def insert_image(self, dt):
self.fl.add_widget(Image(source="HeartIcon.png"))
def insertfunc(self):
# do some calculations here
Clock.schedule_once(self.insert_image)
def start_thread(self, instance):
threading.Thread(target=self.insertfunc).start()
TestApp().run()
If you are not doing anything else in the new thread, then you don't actually need another thread. The start_thread() method can just do the:
self.fl.add_widget(Image(source="HeartIcon.png"))
I am writing a code which starts the frontend, runs the backend and then loads the frontend. The frontend consists of TabbedPanel, and the currently displayed tab may be change by backend.
Here's the MRE:
from kivy.app import App
from kivy.uix.button import Button
from kivy.uix.label import Label
from kivy.uix.tabbedpanel import TabbedPanel, TabbedPanelHeader
def button(instance):
instance.parent.parent.switch_to(instance.parent.parent.tab_2) # accessing TabbedPanel without messing with sending
# a variable
def backend(frontend):
# this class represents main backend function. In the result of its execution there might be a need to switch to
# another tab
frontend.switch_to(frontend.tab_2)
class MyTabbedPanel(TabbedPanel):
def __init__(self, **kwargs):
super().__init__()
self.tab_1 = TabbedPanelHeader()
self.tab_2 = TabbedPanelHeader()
self.tab_1.content = Button(text='Tab 1')
self.tab_1.content.bind(on_release=button)
self.tab_2.content = Label(text='Tab 2')
self.add_widget(self.tab_1)
self.add_widget(self.tab_2)
class Application(App):
def build(self):
frontend = MyTabbedPanel()
backend(frontend)
return frontend
Application().run()
The button, which I have added to compare, to switch from tab 1 to tab 2 works just fine, however, the auto swith when starting the app does not work.
What is the problem? Thank you in advance.
At the time that you're calling backend, there is no root widget returned by the build method, let alone a tab to switch to.
One way to solve this, is to schedule the call to the backend for after the build ends, using the Clock module.
def build(self):
frontend = MyTabbedPanel()
# backend(frontend)
from functools import partial
from kivy.clock import Clock
Clock.schedule_once(partial(backend, frontend))
return frontend
You also have to add an args argument to the backend method, because Clock sends a dt value:
def backend(frontend, *args):
this is my script ...
import kivy
from kivy.app import App
from kivy.uix.button import Button
from kivy.uix.image import Image
class MyApp(App):
def build(self):
return Image(source='go.jpg')
MyApp().run()
I won't to reload it becose the image is changing and I won't to see the new won all time
you can use reload() the read the image from the disk again
this will reload even if the original data of the image is updated or changed
self.ids.image1.source = './Images/file.png'
self.ids.image1.reload()
Make your own widget class, and make the image an attribute, so you can reference it. Then use clock to schedule an interval method, to constantly reload the image.
In the example below, the update_pic method is executed once every second.
import kivy
from kivy.app import App
from kivy.uix.button import Button
from kivy.uix.image import Image
from kivy.clock import Clock
from kivy.uix.widget import Widget
class MyImageWidget(Widget):
def __init__(self,**kwargs):
super(MyImageWidget,self).__init__(**kwargs)
self.image = Image(source='go.jpg')
self.add_widget(self.image)
Clock.schedule_interval(self.update_pic,1)
def update_pic(self,dt):
self.image.reload()
class MyApp(App):
def build(self):
return MyImageWidget()
MyApp().run()
You can use the Image.reload method
def build(self):
img = Image(source='go.jpg')
Clock.schedule_interval(lambda dt: img.reload(), 0.2) #5 per second
return img