Python kivy on android with hardware barcode scanner - python

I have a project where I need to integrate a hardware barcode scanner built into an Android Barcode scanning Device (Cipherlab). My app is built and the only part outstanding is reading the barcode. The barcodes are terminated by an enter keycode. The enter keys are being detected but the rest of the barcode does not display in the textinput which has focus.
I have tested the scanner in a text editor and it's not that. So it looks like the text is being scanned in the app as the enter keycode triggers the on_text_validate event.
Any ideas would be greatly appreciated.
main.py
from kivy.app import App
from kivy.lang import Builder
from kivy.clock import Clock
from kivy.uix.screenmanager import ScreenManager, Screen
Builder.load_string('''
<MainScreen>:
text_in: text_in
memberStatus: memberStatus
BoxLayout:
orientation: 'vertical'
Label:
id: memberStatus
TextInput:
id: text_in
multiline: False
on_text_validate:
root.process_barcode()
''')
class MainScreen(Screen):
def process_barcode(self):
self.memberStatus.text = "Read Value:"+ self.text_in.text
self.text_in.text = ""
Clock.schedule_once(lambda *args: setattr(self.text_in, 'focus', True))
def on_enter(self):
self.memberStatus.text = "Text Input has focus"
Clock.schedule_once(lambda *args: setattr(self.text_in, 'focus', True))
class MyApp(App):
def build(self):
sm = ScreenManager()
sm.add_widget(MainScreen(name="screen_main"))
return sm
if __name__ == '__main__':
MyApp().run()

Related

How to make kivy app from different py files

I am trying to make an app out of different .py files. But I don't know how to add them together, I have one main file, and one login file with plans to add a lot more, but with these I'm experimenting right now. They are pretty basic for now until I figure out this "bonding" between them and then I will start adding some more complex stuff. I tried couple of things and they didn't work, but I left them in code for you to see (I tried to make the app to start with MainWindow, and on press of the first button it goes to login page*). Here's the code and please help me.
*Right now when I press the button it gives me this error: OSError: exception: access violation writing 0x0000000080006010
this is main.py:
from kivy.lang import Builder
from kivy.app import App
import login
from kivy.uix.screenmanager import Screen
kv = Builder.load_string('''
<MainWindow>:
GridLayout:
cols:1
GridLayout:
rows:5
Button:
text:"NOVA ROBA"
on_release:
root.call_login()
Button:
text:"KUPCI"
Button:
text:"PRODATO"
Button:
text: "AGRONOMI"
Button:
text: "STANJE U MAGACINU"
''')
class MainWindow(Screen):
def call_login(self):
login.app().run()
pass
class main_app(App):
def build(self):
return MainWindow()
if __name__ == '__main__':
main_app().run()
this is login.py:
from kivy.lang import Builder
from kivy.uix.screenmanager import Screen
from kivy.app import App
class Login(Screen, App):
def build(self):
return
pass
kv = Builder.load_string('''
<Login>:
name:"login"
GridLayout:
rows:2
GridLayout:
cols:2
Label:
text:"Password: "
TextInput:
id:passwd
multiline: False
Button:
text: "Submit"
on_release:
passwd.text = ""
''')
class app(App):
def build(self):
return Login()
if __name__ == "__main__":
app().run()
You are creating 2 apps, which is not needed. Instead of inheriting from both Screen and App in the Loginscreen, inherit only from Screen. Then create a ScreenManager in your main.py's build method and then add the imported loginscreen as a widget, to switch to the new screen, use self.manager.current = "login" in the call_login method of MainWindow
class app(App):
def build(self):
sm = ScreenManager()
sm.add_widget(MainWindow())
sm.add_widget(Login())
return sm

Browse an image file and display it in a kivy window

I am a beginner in Kivy and trying to browse an image file using kivy fileChooser and then displaying it on the window. Bellow you find my code but it wouldn't do the task. It just displays '?PNG' on the console. Please, check this out with me !
import kivy
from kivy.app import App
from kivy.uix.boxlayout import BoxLayout
from kivy.lang import Builder
from kivy.uix.image import Image
import os
Builder.load_string("""
<MyWidget>:
id: my_widget
Button
text: "open"
on_release: my_widget.open(filechooser.path,
filechooser.selection)
FileChooserListView:
id: filechooser
on_selection: my_widget.selected(filechooser.selection)
""")
class MyWidget(BoxLayout):
def open(self, path, filename):
with open(os.path.join(path, filename[0])) as f:
print f.read()
def selected(self, filename):
return Image(source=filename[0])
class MyApp(App):
def build(self):
return MyWidget()
if __name__ == '__main__':
MyApp().run()
Try this:
I exclude the open button, and just display it when selected.
So we add an Image widget, and set its source when selected.
from kivy.app import App
from kivy.uix.boxlayout import BoxLayout
from kivy.lang import Builder
Builder.load_string("""
<MyWidget>:
id: my_widget
FileChooserListView:
id: filechooser
on_selection: my_widget.selected(filechooser.selection)
Image:
id: image
source: ""
""")
class MyWidget(BoxLayout):
def selected(self,filename):
self.ids.image.source = filename[0]
class MyApp(App):
def build(self):
return MyWidget()
if __name__ == '__main__':
MyApp().run()
This is just a minimal example. It will throw an error if you go a directory up. So you need to handle that.
Easy fix:
class MyWidget(BoxLayout):
def selected(self,filename):
try:
self.ids.image.source = filename[0]
except:
pass

Kivy's ScreenManager and Popups don't want to work together

as stated in the title - I'm stuck. I've been playing with the code around and everything works as long as I keep ScreenManager and Popup separate. Once combined - they refuse to cooperate. Anyway, here is the simple app that shows the problem I'm having.
from kivy.lang import Builder
from kivy.app import App
from kivy.uix.gridlayout import GridLayout
from kivy.uix.popup import Popup
from kivy.uix.screenmanager import Screen, ScreenManager
class First(GridLayout,Screen):
def show_popup(self):
Popp().open()
pass
class Second(Screen):
pass
class Popp(Popup):
pass
class ScreenManagement(ScreenManager):
pass
app = Builder.load_file("main.kv")
class MainApp(App):
def build(self):
return app
if __name__ == "__main__":
MainApp().run()
And main.kv file
ScreenManagement:
First:
Second:
<First>:
name:"First"
rows: 2
Button:
text: "FirstButton"
on_release: app.root.current = "Second"
Button:
text: "Show popup"
on_release: root.show_popup()
<Second>:
name:"Second"
Button:
text: "BUTTON"
on_release: app.root.current = "First"
<Popp>:
title: "testing"
text: "Hello world"
size_hint: None,None
size: 400,400
auto_dismiss: False
Button:
text: "Okay"
on_press: root.dismiss()
App starts, first and second screen are working but when trying to get popup up I end up with:
kivy.uix.popup.PopupException: Popup can have only one widget as content
Somehow Screen is seen as a widget inside of Popp? Or am I terribly misinterpreting kivy docs?
It's a bug with loading kv file, it should throw an exception in this case.
What you are doing in the code is loading the kv file twice, what causes some weird behavior. Just delete the Builder.load_file(..) and it will work. The file is going to be loaded automatically.
Also, never do double subclassing of widgets like class First(GridLayout, Screen) as it might lead to some problems. Instead, create a grid layout inside the screen.
Put the elements in the Popup inside a layout, for example: Boxlayout.
Here's what I mean:
<Popp>:
title: "testing"
BoxLayout:
orientation: 'vertical'
size_hint: None,None
size: 400,400
Label:
text: "Hello world"
Button:
text: "Okay"
on_press: root.dismiss()
I have same problem with using kivy Builder.load_file and Popup, they dont work together.
the solution is simple, build popup in python code side. this is a loading popup example:
python:
from kivy.app import App
from kivy.uix.popup import Popup
from kivy.factory import Factory
from kivy.properties import ObjectProperty
from kivy.clock import Clock
from kivy.lang import Builder
from kivy.uix.popup import Popup
from kivy.uix.image import Image
from kivy.uix.label import Label
from kivy.uix.boxlayout import BoxLayout
import time, threading
buildKV = Builder.load_file("example.kv")
class ExampleApp(App):
def show_popup(self):
content = BoxLayout(orientation= "vertical")
image=Image(source= 'files/loading.gif', anim_delay= 0)
label=Label(text= 'Model is Running.\nBe Patient Please.')
content.add_widget(image)
content.add_widget(label)
self.popup = Popup(title='Model is Running.',
size_hint=(.250, .785),
content=content, auto_dismiss=False)
self.popup.open()
def process_button_click(self):
# Open the pop up
self.show_popup()
# Call some method that may take a while to run.
# I'm using a thread to simulate this
mythread = threading.Thread(target=self.something_that_takes_5_seconds_to_run)
mythread.start()
def something_that_takes_5_seconds_to_run(self):
thistime = time.time()
while thistime + 10 > time.time(): # 5 seconds
time.sleep(1)
# Once the long running task is done, close the pop up.
self.pop_up.dismiss()
if __name__ == "__main__":
ExampleApp().run()
kivy:
BoxLayout:
Button:
height: 40
width: 100
size_hint: (None, None)
text: 'Click Me'
on_press: app.process_button_click()

How I can use Kivy (Python) camera

I try to use uix.camera widget and show some wideo from my web-camera.
I looked into the documentation and try to use this simply code. But it's just show me a white creen withoud any video (I enabled playing).
What I'm doing wrong?
Maybe some useful docs\tutorial exist (because from official documentation I understanding a little from many). Thanks for any help.
import kivy
kivy.require('1.9.1')
from kivy.app import App
from kivy.uix.label import Label
from kivy.uix.camera import Camera
class MainApp(App):
def build(self):
return Camera(play=True)
if __name__== "__main__":
MainApp().run()
You need to specify resolution. In my case, I also needed to specify index=1, that is the second camera plugged in my computer.
Example:
import kivy
kivy.require('1.9.1')
from kivy.app import App
from kivy.uix.label import Label
from kivy.uix.camera import Camera
class MainApp(App):
def build(self):
return Camera(play=True, index=1, resolution=(640,480))
if __name__== "__main__":
MainApp().run()
It seems like you need to set resolution=[x, y] property besides play=True, because the default one doesn't work.
The following are the Kivy examples to use camera.
from kivy.app import App
from kivy.lang import Builder
kv = '''
BoxLayout:
orientation: 'vertical'
Camera:
id: camera
resolution: 399, 299
BoxLayout:
orientation: 'horizontal'
size_hint_y: None
height: '48dp'
Button:
text: 'Start'
on_release: camera.play = True
Button:
text: 'Stop'
on_release: camera.play = False
'''
class CameraApp(App):
def build(self):
return Builder.load_string(kv)
if __name__ == '__main__':
CameraApp().run()
Example 2:-
from kivy.app import App
from kivy.lang import Builder
from kivy.uix.boxlayout import BoxLayout
import time
Builder.load_string('''
<CameraClick>:
orientation: 'vertical'
Camera:
id: camera
resolution: (640, 480)
play: False
ToggleButton:
text: 'Play'
on_press: camera.play = not camera.play
size_hint_y: None
height: '48dp'
Button:
text: 'Capture'
size_hint_y: None
height: '48dp'
on_press: root.capture()
''')
class CameraClick(BoxLayout):
def capture(self):
'''
Function to capture the images and give them the names
according to their captured time and date.
'''
camera = self.ids['camera']
timestr = time.strftime("%Y%m%d_%H%M%S")
camera.export_to_png("IMG_" + timestr)
print("Captured")
class TestCamera(App):
def build(self):
return CameraClick()
TestCamera().run()
I just faced the same problem and found out that Kivy is very slow when creating widget for usb webcam device.
If you have set the index and other parameters properly, maybe just waiting a little longer for Kivy to create the video widget then you could see the webcam view shows in the window, but I am still trying to find out the reason why Kivy takes so long time (about a minute) to create usb webcam widget, hope someone could give some advices about this problem.
I tried using the code as suggested by #Thiago. It didnt work, I suspect its not detecting my USB camera that I have plugged into my Raspberry Pi4.
Following is the code I am using and I also ran a query in the terminal to obtain the camera type that is plugged in (only one plugged in).
The Code:
import kivy
from kivy.app import App
from kivy.uix.label import Label
from kivy.uix.camera import Camera
class MainApp(App):
def build(self):
return Camera(play=True, index=0, resolution=(640,480))
if __name__== "__main__":
MainApp().run()
Terminal Output:
pi#raspberrypi:~ $ v4l2-ctl --list-formats
ioctl: VIDIOC_ENUM_FMT
Type: Video Capture
[0]: 'MJPG' (Motion-JPEG, compressed)
[1]: 'YUYV' (YUYV 4:2:2)

Editing widgets in another Kivy screen

I'm trying to get the nickname from the intro screen and then build the chat screen using this nickname in a label. However, I can't get my function to work with ids properly.
.kv:
#: import FadeTransition kivy.uix.screenmanager.FadeTransition
Screens:
transition: FadeTransition()
Intro
Chat
<Intro>:
id: intro
TextInput:
id: intro_text
...
Button:
...
on_press: root.intro_bt_press()
<Chat>:
name: "main"
Label:
id: lb_name
.py:
from kivy import require
require("1.9.1")
from kivy.app import App
from kivy.uix.screenmanager import Screen, ScreenManager, FadeTransition
from kivy.lang import Builder
nick = ""
class Chat(Screen):
lb_name.text = "Chat with {}".format(nick)
class Intro(Screen):
global nick
def intro_bt_press(self):
nick = intro_text.text
App.get_running_app().root.current = "main"
class Screens(ScreenManager):
pass
Screens = Builder.load_file("chat.kv")
class Chat(App):
def build(self):
return Screens
if __name__ == "__main__":
Chat().run()
So when the button is pressed, I want to get the text from TextInput, switch to the main screen and format the label on that screen with the text. I can't assign the text to the variable "nick" because it says that it's not defined. And the same goes for lb_name, but I can't even get past the first error. What am I missing before the id to tell Python, where in the kv file to look?
The ids assigned in kv are available in the ids
property. if you want to access the widgets in your Python file, use something like self.ids['intro_text'].text in intro_bt_press.
However, the desired behaviour can be achieved just using the kv language:
This is chat.kv:
#: import FadeTransition kivy.uix.screenmanager.FadeTransition
<Screens#ScreenManager>:
Screens:
transition: FadeTransition()
Intro
Chat
<Intro#Screen>:
BoxLayout:
TextInput:
id: intro_text
Button:
on_press:
root.manager.get_screen('main').ids.lb_name.text = root.ids.intro_text.text
root.manager.current = "main"
<Chat#Screen>:
name: "main"
Label:
id: lb_name
And this is chat.py:
from kivy.app import App
class ChatApp(App):
pass
if __name__ == "__main__":
ChatApp().run()

Categories