Python kivy text to speech and Popup in parallel - python

I am trying to implement a warning which is using text to speech and a visual warning as popup which should disappear after few seconds. I am using kivy for the user interface. At the moment the code is running with the popup and the voice warning, but the problem is, that the voice warning starts first (I would rather like the popup warning to be first) and I additionally would like both processes to start at the same time. I was not able to solve this issue using multiprocessing.Process(target.display_warning_popup).start() and multiprocessing.Process(target.display_warning_voice).start(). Followed by multiprocessing.Process(target.display_warning_popup).join() and multiprocessing.Process(target.display_warning_voice).join().
This is a snippet of the code that I am using.
# imports
import pyttsx3 # for text to speech
from kivy.uix.popup import Popup
from kivy.uix.label import Label
from kivy.clock import Clock
class MainApp(App):
engine = pyttsx3.init()
# function for displaying popup
def display_warning_popup():
content = Label(text="Please reduce the temperature.")
content.color = (1, 1, 1, 1)
popup = Popup(title="Warning",
content=content,
size_hint=(None, None),
size=(350, 150))
popup.open()
Clock.schedule_once(popup.dismiss, 2)
# function for text to speech
def display_warning_voice(self):
self.engine.say("Temperature is too high")
self.engine.runAndWait()
# function for warning
def warning(self, is_temperature_too_high):
if is_temperatrue_too_high:
self.display_warning_popup()
self.display_warning_voice()

Binding the voice warning to the on_open event of the Popup results in both warnings appearing at about the same time. The Popup class is an extension of the ModalView class, and the documentation is here.
After incorporating this change and correcting some other minor problems with the code, here is what your code looks like:
# imports
import pyttsx3 # for text to speech
from kivy.app import App
from kivy.uix.button import Button
from kivy.uix.popup import Popup
from kivy.uix.label import Label
from kivy.clock import Clock
class MainApp(App):
engine = pyttsx3.init()
def build(self):
return Button(text='click here', on_press=self.warning)
# function for displaying popup
def display_warning_popup(self):
content = Label(text="Please reduce the temperature.")
content.color = (1, 1, 1, 1)
popup = Popup(title="Warning",
content=content,
size_hint=(None, None),
size=(350, 150))
popup.bind(on_open=self.display_warning_voice)
popup.open()
Clock.schedule_once(popup.dismiss, 2)
# function for text to speech
def display_warning_voice(self, *args):
self.engine.say("Temperature is too high")
self.engine.runAndWait()
# function for warning
def warning(self, is_temperature_too_high):
self.display_warning_popup()
MainApp().run()

Related

kivy widgets doesn't appear just show black screen

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()

How do I get the kivy Window.softinput_mode = 'below_target' to move the TextInput box above the virtual keyboard?

I'm using python 3.8.6 and kivy 2.1.0.
When the text input box gets focus, the keyboard pops up and covers the TextInput box. I've added the 2 lines below to force the keyboard to be below the target TextInput box, but it does not work as expected.
Window.keyboard_anim_args = {"d":.2,"t":"linear"}
Window.softinput_mode = "below_target"
I've also tried 'pan' and 'resize'. The code runs with no errors, but none of these settings has any effect on the behavior, so I'm sure I'm missing something obvious, but it's not obvious to me:-(. Any help is greatly appreciated. The full code follows:
from kivy.app import App
from kivy.core.window import Window
from kivy.uix.button import Button
from kivy.uix.textinput import TextInput
from kivy.uix.boxlayout import BoxLayout
from kivy.config import Config
Window.keyboard_anim_args = {"d":.2,"t":"linear"}
Window.softinput_mode = "below_target"
#Window.softinput_mode = 'pan'
#Window.softinput_mode = 'resize'
class ClearApp(App):
def build(self):
self.box = BoxLayout(orientation='horizontal', spacing=10)
self.txt = TextInput(hint_text='Write here',
keyboard_mode='auto',
size_hint=(.5,.1))
self.btn = Button(text='Clear All',
on_press=self.clearText, size_hint=(.1,.1))
self.box.add_widget(self.txt)
self.box.add_widget(self.btn)
return self.box
def clearText(self, instance):
self.txt.text = ''
'''
if Config:
_is_desktop = Config.getboolean('kivy', 'desktop')
_keyboard_mode = Config.get('kivy', 'keyboard_mode')
if _is_desktop:
Config.set('kivy', 'keyboard_mode','system')
Config.write()
else:
Config.set('kivy', 'keyboard_mode','systemanddock')
Config.write()
'''
Config.set('kivy', 'keyboard_mode','dock')
Config.write()
ClearApp().run()
Use import Config before import App
which help you to focus and show your keyboard in the UI
for eg.
from kivy.config import Config
from kivy.app import App
use these these line in your code
This function is available only in the master kivy version. so in your buildozer.spec file in the requirements put kivy==master when you are adding kivy to the requirements

How to run a Method on the exit of a kivy app

I would like to run a Method when the user tries to exit the app , kind of like a "are you sure you want to exit" or "Do you want to save the file" type of message whenever the user tries to exit by clicking the Exit button on top of the window
Some thing like
on_quit: app.root.saveSession()
If you want your application to simply run things after the GUI has closed, the easiest and smallest approach would be to place any exit code after TestApp().run(). run() creates a endless loop which also clears any event-data from within kivy so it doesn't hang. That endless loop breaks as soon as the window/gui instance dies. So there for, any code after will execute only after the GUI dies too.
If you want to create a graceful shutdown of the GUI with for instance socket-closing events or a popup asking the user if that's what they really want to do, then creating a hook for the on_request_close event is the way to go:
from kivy.config import Config
Config.set('kivy', 'exit_on_escape', '0')
from kivy.app import App
from kivy.uix.label import Label
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.button import Button
from kivy.uix.popup import Popup
from kivy.core.window import Window
class ChildApp(App):
def build(self):
Window.bind(on_request_close=self.on_request_close)
return Label(text='Child')
def on_request_close(self, *args):
self.textpopup(title='Exit', text='Are you sure?')
return True
def textpopup(self, title='', text=''):
"""Open the pop-up with the name.
:param title: title of the pop-up to open
:type title: str
:param text: main text of the pop-up to open
:type text: str
:rtype: None
"""
box = BoxLayout(orientation='vertical')
box.add_widget(Label(text=text))
mybutton = Button(text='OK', size_hint=(1, 0.25))
box.add_widget(mybutton)
popup = Popup(title=title, content=box, size_hint=(None, None), size=(600, 300))
mybutton.bind(on_release=self.stop)
popup.open()
if __name__ == '__main__':
ChildApp().run()
Courtesy of pythonic64 who created a gist on the topic in a issue way back when.

Prevent the EXIT of a kivy App on Android with the ESCAPE ARROW

I would like to prevent the EXIT of a kivy App on Android with the ESCAPE ARROW.
When I write exit_on_escape = 0 in the config.ini file, it does not change anything (however on WINDOWS 8 with the Esc key this works).
I have also tried unsuccessfully to intercept the on_request_close.
import kivy
kivy.require('1.0.8')
from kivy.core.window import WindowBase
from kivy.uix.widget import Widget
from kivy.app import App
from kivy.clock import Clock
class Test(Widget):
def __init__(self, **kwargs):
super(Test,self).__init__(**kwargs)
class TestApp(App):
def build(self):
Clock.schedule_once(self.my_callback, 0)
return Test()
def my_callback(self,*dt):
print("mycallback")
win=self._app_window
win.fullscreen=1 #OK
win.bind(on_request_close=self.alwaystrue)
def alwaystrue(*largs, **kwargs) :
print("alwaystrue")#never happens ...
return True
if __name__ == '__main__':
TestApp().run()
Do something like this in your App class:
from kivy.app import App
from kivy.core.window import Window
class MyApp(App):
def build(self):
self.bind(on_start=self.post_build_init)
# do all your normal stuff as well
return whatever
def post_build_init(self,ev):
if platform() == 'android':
import android
android.map_key(android.KEYCODE_BACK, 1001)
win = Window
win.bind(on_keyboard=self.key_handler)
def key_handler(self, window, keycode1, keycode2, text, modifiers):
if keycode1 == 27 or keycode1 == 1001:
# Do whatever you want here - or nothing at all
# Returning True will eat the keypress
return True
return False
This is probably not all be necessary (using the intermediate post_build_init() method and the android.map_key() thing), but I originally got it from a mailing post and I don't think I have an updated version. Anyway, it works for me.
Add the following code snippet just below the import kivy statement
from kivy.config import Config
Config.set('kivy', 'exit_on_escape', '0')
Here is a working example, how to use on_request_close.
The line:
Config.set('kivy', 'exit_on_escape', '0')
disables the Esc -button.
from kivy.config import Config
Config.set('kivy', 'exit_on_escape', '0')
from kivy.app import App
from kivy.uix.label import Label
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.button import Button
from kivy.uix.popup import Popup
from kivy.core.window import Window
class ChildApp(App):
def build(self):
Window.bind(on_request_close=self.on_request_close)
return Label(text='Child')
def on_request_close(self, *args):
self.textpopup(title='Exit', text='Are you sure?')
return True
def textpopup(self, title='', text=''):
"""Open the pop-up with the name.
:param title: title of the pop-up to open
:type title: str
:param text: main text of the pop-up to open
:type text: str
:rtype: None
"""
box = BoxLayout(orientation='vertical')
box.add_widget(Label(text=text))
mybutton = Button(text='OK', size_hint=(1, 0.25))
box.add_widget(mybutton)
popup = Popup(title=title, content=box, size_hint=(None, None), size=(600, 300))
mybutton.bind(on_release=self.stop)
popup.open()
if __name__ == '__main__':
ChildApp().run()

Kivy: Multiple items in a popup wont work

I am trying to use multiple items in a popup with kivy in python. I would
like to find out how to make this work. I am not sure if it has to do with the fact
that the script is on my phone and not made for computer.
Here is a little example script that I am asking you to help make work for future reference.
import kivy
from kivy.lang import Builder
from kivy.uix.popup import Popup
from kivy.uix.textinput import TextInput
from kivy.uix.label import Label
popup = Popup(title='Test popup',
content=Label(text='Hello world'),
TextInput(text='Hi'), #Here is what I am trying to make work
size_hint=(None, None), size=(400, 400))
So you can see it is two objects in one content of the popup. I am sure this is possible
because I've seen it on kivy apps in the appstore, but not sure how to do it myself.
The content of a Popup can only be a single widget. You cannot add two widgets like you're trying to do.
To accomplish what you're trying to do you'll have to add the label and text input to e.g. a boxlayout and then add the boxlayout to content. Here's an example that should work:
from kivy.uix.popup import Popup
from kivy.uix.textinput import TextInput
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.label import Label
box = BoxLayout()
box.add_widget(Label(text='Hello world'))
box.add_widget(TextInput(text='Hi'))
popup = Popup(title='Test popup', content=box, size_hint=(None, None), size=(400, 400))
You can achieve this using kv file.
:
orientation:'vertical'
Label:
text: 'Hello World'
Button:
text: 'Press Me'
In python file:
def openPop(self):
self.pop = Popup(title='Test',content=Content(),auto_dismiss=True)
self.pop.open()
you need to do this:
def __init__(self, **kwargs):
super().__init__(**kwargs)
self.super_box = BoxLayout(orientation = "vertical")
self.pn = TextInput(text = "projectname") # TODO: Project name input
self.super_box.add_widget(self.pn)
"""Create button: Creates a new project repo"""
cb = Button(text="Create")
cb.bind(on_release = lambda x: print("a new project repo gets created"))
self.super_box.add_widget(cb)

Categories