Below is a "Hello World" code snippet that I reworked from KivMob examples on GitHub. The examples weren't really helpful because they lacked proper comments, so I didn't know what was going on.
I can't see any ads when I port this app to Android. I'm also failing to see the logic of how and where the ads are supposed to appear. Can someone please help me to get KivMob to show up on Android?
from kivmob import KivMob
import kivy.utils
from kivy.app import App
from kivy.lang import Builder
from kivy.config import Config
from kivy.properties import ListProperty
from kivy.utils import platform
from kivy.uix.floatlayout import FloatLayout
from kivy.uix.behaviors import ButtonBehavior
from kivy.uix.label import Label
if platform not in ('android', 'ios'):
# Approximate dimensions of mobile phone.
Config.set('graphics', 'resizable', '0')
__version__ = "1.0"
Builder.load_string("""
#:import kivy kivy
<KivMobDemoUI>:
canvas.before:
Rectangle:
pos: self.pos
size: self.size
FloatLayout:
BoxLayout:
orientation: "vertical"
AnchorLayout:
CustomButton:
text: "Toggle Banner"
size_hint: 0.8, 0.2
on_release: app.toggle_banner()
<CustomButton>:
canvas.before:
Color:
rgba: self.box_color
RoundedRectangle:
pos: self.pos
size: self.size
color: (1, 1, 1, 1)
bold: True
text_size: self.width, None
height: self.texture_size[1]+size_hint_y: None
text_size: self.width, None
height: self.texture_size[1] + sp(20)
halign: 'center'
valign: 'middle'
""")
class KivMobDemoUI(FloatLayout):
pass
class CustomButton(ButtonBehavior, Label):
box_color = ListProperty(kivy.utils.get_color_from_hex("56b669"))
prv_color = ListProperty(kivy.utils.get_color_from_hex("56b669"))
def __init__(self, **kwargs):
super(CustomButton, self).__init__(**kwargs)
self.always_release = True
def on_press(self):
self.prv_color = self.box_color
self.box_color = (0,0,0,1)
def on_release(self):
self.box_color = self.prv_color
class KivMobDemo(App):
def build(self):
APP_ID = "ca-app-pub-ENTER#"
BANNER_ID = "ca-app-pub-ENTER#"
TEST_DEVICE_ID = "ca-app-pub-ENTER#"
self.ads = KivMob(APP_ID)
self.ads.add_test_device(TEST_DEVICE_ID)
self.ads.new_banner({"unitID": BANNER_ID})
self.ads.show_banner()
self.ads.request_banner()
self.toggled = False
return KivMobDemoUI()
def on_pause(self):
return True
def on_resume(self):
return True
def toggle_banner(self):
if not self.toggled:
self.ads.show_banner()
else:
self.ads.hide_banner()
self.toggled = not self.toggled
if __name__ == "__main__":
KivMobDemo().run()
You have to add some notes in your buildozer.spec file:
requirements = kivy, android, jnius, kivmob
...
android.permissions = INTERNET, ACCESS_NETWORK_STATE
android.api = 27
android.minapi = 21
android.sdk = 24
android.ndk = 17b
android.gradle_dependencies = 'com.google.firebase:firebase-ads:10.2.0'
p4a.branch = master
android.meta_data = com.google.android.gms.ads.APPLICATION_ID=ca-app-pub-3940256099942544~3347511713
Related
Im trying to iterate through a list of objects in python and add them to gridlayout in my .kv file.
main.py file:
import kivy
from kivy.app import App
from kivy.uix.screenmanager import ScreenManager, Screen
kivy.require('2.1.0')
posts = [('post1 title', 'post1 content), ('post2 title', 'post2 content)]
class Post:
def __init__(self, title, content):
self.title = title
self.content = content
class MainPage(Screen):
posts_to_display = [Post(post[1], post[2]) for post in posts]
class Window(App):
def build(self):
sm = ScreenManager()
sm.add_widget(MainPage(name="homepage"))
return sm
if __name__ == '__main__':
Window().run()
.kv file:
#kivy 2.1.0
<MainPage>:
canvas.before:
Color:
rgba: (28/255, 31/255, 33/255, 1)
Rectangle:
pos:self.pos
size:self.size
ScrollView:
GridLayout:
rows: 5
size_hint_y: 1.5
spacing: 10, 10
padding: 10, 10
How can i add all the elements from posts_to_display to gridlayout?
I tried importing kivy.uix.gridlayout but couldnt find a way to interact with the .kv file
You can do some thing like this, if you dont want scrollable GridLayout, just remove ScrollView and self.size_hint_y = None; self.height = 50.
from kivy.app import App
from kivy.uix.button import Button
from kivy.lang.builder import Builder
from kivy.uix.screenmanager import Screen
from kivy.clock import Clock
posts = [(f'title {i}', f'content {i}') for i in range(10)]
KV = """
<MainPage>:
canvas.before:
Color:
rgba: (28/255, 31/255, 33/255, 1)
Rectangle:
pos:self.pos
size:self.size
ScrollView:
GridLayout:
id: grid
rows: 5
size_hint_y: None
spacing: dp(10)
padding: [dp(10), ]
BoxLayout:
ScreenManager:
MainPage:
id: mp
name: "homepage"
"""
class Post(Button):
def __init__(self, title: str, content: str, **kwargs):
super().__init__(**kwargs)
self.text = title
self.content = content
self.size_hint_y = None
self.height = 50
class MainPage(Screen):
posts_to_display = [Post(post[0], post[1]) for post in posts]
def post_add(self):
for widget in self.posts_to_display:
self.ids.grid.add_widget(widget)
class TestApp(App):
def build(self):
return Builder.load_string(KV)
def on_start(self):
Clock.schedule_once(lambda dt: self.root.ids.mp.post_add())
if __name__ == '__main__':
TestApp().run()
I'm very new to Kivy and have been constantly running into issues and errors. A common problem I have is running a python program, seeing that the .kv file is displaying a window, but there is nothing inside the window. The purpose of the code is to display a window starting on the LoginScreen and switching between a separate HomeScreen with a press of a button. Any solutions would be helpful. Thanks.
Python file:
import os
from kivy.app import App
from kivy.config import Config
Config.set('graphics', 'width', '400')
Config.set('graphics', 'height', '600')
from kivy.uix.screenmanager import ScreenManager, Screen
from kivy.uix.floatlayout import FloatLayout
from kivy.uix.gridlayout import GridLayout
from kivy.uix.textinput import TextInput
from kivy.uix.widget import Widget
from kivy.uix.label import Label
from kivy.uix.button import Button
from kivy.uix.popup import Popup
from kivy.lang import Builder
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.anchorlayout import AnchorLayout
from kivy.uix.stacklayout import StackLayout
from kivy.metrics import dp
from kivy.properties import ObjectProperty, StringProperty, BooleanProperty, Clock
from kivy.graphics.vertex_instructions import Line, Rectangle, Ellipse
from kivy.graphics.context_instructions import Color
#transition_direction = StringProperty('down') <--- Ignore this
class HomeScreen(Screen):
def returnBtn(self):
sm.current = 'LoginScreen'
class LoginScreen(Screen):
email = ObjectProperty(None)
password = ObjectProperty(None)
login_lst = []
passwordStudents = open('passwords/passwordStudents.txt').read()
passwordTeachers = open('passwords/passwordTeachers.txt').read()
passwordAdmin = open('passwords/passwordAdmin.txt').read()
def loginBtn(self):
self.login_lst.append(self.email.text)
self.login_lst.append(self.password.text)
if self.login_lst[0] and self.login_lst[-1] in self.passwordStudents:
print('Student: True')
print('Teacher: False')
print('Admin: False')
self.reset()
self.home()
elif self.login_lst[0] and self.login_lst[-1] in self.passwordTeachers:
print('Student: False')
print('Teacher: True')
print('Admin: False')
self.reset()
self.home()
elif self.login_lst[0] and self.login_lst[-1] in self.passwordAdmin:
print('Student: False')
print('Teacher: False')
print('Admin: True')
self.home()
self.reset()
else:
print('Student: False')
print('Teacher: False')
print('Admin: False')
self.reset()
def reset(self):
self.email.text = ''
self.password.text = ''
def home(self):
#transition_direction = 'down' <--- Ignore this
sm.current = 'HomeScreen'
class WindowManager(ScreenManager):
pass
sm = WindowManager()
screens = [LoginScreen(name='login'), HomeScreen(name='home')]
for screen in screens:
sm.add_widget(screen)
sm.current = 'login'
class MyApp(App):
def build(self):
return sm
if __name__ == '__main__':
MyApp().run()
Kivy file:
<LoginScreen>:
name: "login"
email: email
password: psswrd
BoxLayout:
orientation: "vertical"
Label:
text: "Login"
pos: 0, root.height/3
font_size: 100
GridLayout:
cols: 2
Label:
size_hint: None, None
width: "175dp"
height: "50dp"
text: "Email:"
font_size: 50
TextInput:
id: email
multiline: False
size_hint: None, None
width: "200dp"
height: "50dp"
font_size: (root.width**2 + root.height**2) / 14**4
GridLayout:
cols: 2
Label:
size_hint: None, None
width: "175dp"
height: "50dp"
text: "Password:"
font_size: 50
TextInput:
id: psswrd
multiline: False
size_hint: None, None
width: "200dp"
height: "50dp"
password: True
font_size: (root.width**2 + root.height**2) / 14**4
FloatLayout:
Button:
size_hint: None, None
width: "150dp"
height: "100dp"
pos: root.width/2 - 150, root.height/4 - 150
text: "Submit"
font_size: 60
on_release:
root.loginBtn()
<HomeScreen>:
name: "home"
Button:
text: "Go back"
on_release:
root.returnBtn()
Edit: I have noticed that the code runs when I comment out these three lines. Why is that?
class MyApp(App):
#def build(self):
# return sm
pass
#if __name__ == '__main__':
MyApp().run()
You are building your screens before your kv file is loaded, so the LoginScreen and the HomeScreen have nothing in them. If your kv file is correctly named (my.kv) then it will be automatically loaded when MyApp().run() is run and you can build your screens inside the build() method. If your kv file is not named that way, you can just add a call to Builder.load_file() in your build() method before your create the screens.
I've created a Screen with a boxlayout and its children.
I wanna print size of the label "Hello" in the boxlayout, which has id:shadow_label
This size must be relative. But it's [100, 100]
Why?
What could I give more details for this post? Could this behavior be due to AnchorLayout?
Here is my code
kv file:
<WellcomeScreen>:
box_layout: wellcome_box
BoxLayout:
id: wellcome_box
orientation: 'vertical'
pos: self.parent.pos
size: self.parent.size
padding: [30, 30]
spacing: 10
canvas.before:
Rectangle:
source: 'Data\game background.png'
pos: self.pos
size: self.size
Label:
id:shadow_label
size_hint: (1, .6)
font_size: self.height/12
text_size: self.width-10, None
color: 'purple'
halign: "center"
text: "Hello"
AnchorLayout:
size_hint: (1,.3)
Button:
canvas.before:
Rectangle:
source: "Data\Button_start.png"
pos: self.pos
size: self.size
pos_hint: {"center_x":0.5,"center_y":0.5}
size_hint: (None, None)
size: (self.parent.height/4*3, self.parent.height/4*3)
background_color: (1,1,1,0)
font_size: self.height/4
text_size: self.width, None
text: "START"
color: "yellow"
bold: True
halign: 'center'
on_press:
root.manager.transition.direction = 'left'
root.manager.current = 'login'
python
from kivymd.app import MDApp
from kivy.uix.screenmanager import ScreenManager, Screen
from kivymd.uix.label import MDLabel
from kivy.uix.behaviors import ButtonBehavior
from kivy.properties import ObjectProperty
from kivy.config import Config
Config.set('graphics', 'resizable', '0')
Config.set('graphics', 'width', '420')
Config.set('graphics', 'height', '860')
class WellcomeScreen(Screen):
user_name = ObjectProperty()
box_layout = ObjectProperty()
wellcome_label = ObjectProperty()
def __init__(self, **kwargs):
super(WellcomeScreen, self).__init__(**kwargs)
class StartButton(ButtonBehavior, MDLabel):
def __init__(self, **kwargs):
super(StartButton, self).__init__(**kwargs)
self.background_normal = "Data\Button_start.png"
self.text = "START"
self.text_color = "yellow"
self.color = "white"
self.halign = "center"
class FastReadApp(MDApp):
def build(self):
sm = ScreenManager()
screen_wellcome = WellcomeScreen(name='wellcome')
sm.add_widget(screen_wellcome)
print(screen_wellcome.ids.shadow_label.size)
return sm
if __name__ == '__main__':
app = FastReadApp()
app.run()
There is the screen of my app:
You are printing the size of the label before its size is set, so you see the default size of (100,100). Just delay the print until the size is set. Use Clock.schedule_once() or use a Button to trigger the print.
I have been trying to create a kivy camera scanner from a number of sources (I would use the zbarcam if I could, but the garden.xcamera module will not import, therefore I am trying to create something similar).
Problem
The problem is the camera does not read or update the texture continuously nor is there a way that I can find to capture frame-for-frame from the camera. This means I only get the texture on initialization.
Tried
Firstly, I have tried scheduling an event that will update the texture instance every 0.5 seconds. I could not get the texture instance of the camera because there is some delay in the camera to load, which caused an error.
Secondly, I created an on_texture event in my kv string, but it only reads the texture on initialization.
Thirdly, I tried binding the on_texture event a bit later in the python script, by creating a binding function and calling it as a scheduled event. It did not even get the instance.
Fourthly, I created_triggers and ask_update(callbacks) to the _on_texture() event, but again the script loads to fast before the camera can instantiate crashing the script.
Fifthly, I noticed there is a kivy.core.video module that contains a on_frame attribute. Did re-write my script to use it in conjunction with the kivy.uix.video module, but noticed that the video cannot run without first loading a video file.
Code
import kivy
import gi
kivy.require('1.11.1')
gi.require_version('Gst', '1.0')
from collections import namedtuple
from PIL import Image
from kivy.app import App
from kivy.clock import Clock
from kivy.lang import Builder
from kivy.uix.boxlayout import BoxLayout
from kivy.properties import ListProperty, ObjectProperty
from kivy.uix.camera import Camera
import time
from gi.repository import Gst
import pyzbar.pyzbar
from kivy.uix.modalview import ModalView
Builder.load_string('''
#: import Window kivy.core.window.Window
<ScanPreview>:
auto_dismiss: False
size_hint_x: 0.6
size_hint_y: None
height: Window.height / 9
pos_hint: {'top':0.7, 'x': 0.1}
background_normal: ''
background_color: (1, 1, 1, 0)
background: 'white.png'
Label:
id: sc_data
text: 'See me...'
<ScanCamera>:
orientation: 'vertical'
The_Camera:
id: camera
resolution: root.resolution
on_texture: root._on_texture(camera)
ToggleButton:
text: 'Stop'
on_press: camera.play = not camera.play
size_hint_y: None
height: '48dp'
''')
class ScanPreview(ModalView):
pass
class The_Camera(Camera):
pass
class ScanCamera(BoxLayout):
resolution = ListProperty([640, 480])
symbols = ListProperty([])
code_types = ListProperty(set(pyzbar.pyzbar.ZBarSymbol))
cam_cam = ObjectProperty(The_Camera())
the_preview = ObjectProperty(ScanPreview())
Symb = namedtuple('Symb', ['type','data'])
def __init__(self, **kwargs):
super(ScanCamera, self).__init__(**kwargs)
self.cam_cam.play = True
def _on_texture(self, instance):
#source: https://github.com/kivy-garden/garden.zbarcam/blob/develop
#/zbarcam/zbarcam.py
print(instance)
if not instance.texture == None:
print(instance.texture)
self.symbols = self._detect_qrcode_frame(
texture=instance.texture, code_types=self.code_types)
def _detect_qrcode_frame(cls, texture, code_types):
image_data = texture.pixels
size = texture.size
#source: https://github.com/kivy-garden/garden.zbarcam/blob/develop
#/zbarcam/zbarcam.py
# Fix for mode mismatch between texture.colorfmt and data returned
#by
# texture.pixels. texture.pixels always returns RGBA, so that
#should
# be passed to PIL no matter what texture.colorfmt returns. refs:
# https://github.com/AndreMiras/garden.zbarcam/issues/41
pil_image = Image.frombytes(mode='RGBA', size=size,
data=image_data)
symbols = []
print(pil_image)
print(size)
print(texture.tex_coords)
print(texture.target)
codes = pyzbar.pyzbar.decode(pil_image, symbols=code_types)
for code in codes:
symbol = CameraClick.Symb(type=code.type, data=code.data)
symbols.append(symbol)
print(symbols)
return symbols
class TestCamera(App):
title = 'Scan Camera'
def build(self):
return ScanCamera()
def on_stop(self):
cc = The_Camera()
print('Stop')
cc.play = False
def on_pause(self):
return True
def on_resume(self):
pass
TestCamera().run()
Desired result
The camera's texture must continuously update, which will allow the pyzbar and PIL module to decode the texture?
I don't know if this is how its done, but as I answered my own question I am posting the answer and marking it as such.
Answer
So I managed to solve my question by using the example code here: https://kivy-fork.readthedocs.io/en/latest/_modules/kivy/uix/camera.html and mixing in some functions of zbarcam.
By using self.canvas.ask_update() in the on_texture call it updates the texture. I have added to the code and it now updates the texture continuously and prints the barcode to a togglebutton. At the moment I have just tested it on Ubuntu Bionic Beaver. Will test it on android this weekend.
Answer code
import kivy
import gi
kivy.require('1.11.1')
gi.require_version('Gst', '1.0')
from collections import namedtuple
from PIL import Image as Img
from kivy.app import App
from gi.repository import Gst
import pyzbar.pyzbar
from kivy.uix.image import Image
from kivy.core.camera import Camera as CoreCamera
from kivy.properties import NumericProperty, ListProperty, \
BooleanProperty, ObjectProperty
from kivy.lang import Builder
from kivy.uix.floatlayout import FloatLayout
from kivy.core.window import Window
Builder.load_string('''
#: import Window kivy.core.window.Window
<ScanCamera>:
<BarcWin>:
ActionBar:
pos_hint: {'top': 1, 'right': 1}
color: (1,1,1,1)
canvas.before:
Color:
rgba: (0,0,0,1)
Rectangle:
pos: self.pos
size: self.size
ActionView:
use_separator: True
ActionPrevious:
title: ''
with_previous: False
app_icon: ''
ActionButton:
color: (0,0,0,1)
background_normal: ''
Image:
source: 'gear_2.png'
center_y: self.parent.center_y
center_x: self.parent.center_x
size: self.parent.width /1.7, self.parent.height/ 1.7
allow_stretch: True
ActionButton:
color: (0,0,0,1)
size_hint_x: 0.09
background_normal: ''
Image:
source: 'dustbin_backgrnd_792521.png'
center_y: self.parent.center_y
center_x: self.parent.center_x
size: self.parent.width /1.7, self.parent.height/ 1.7
allow_stretch: True
ScanCamera:
pos_hint: {'top': 0.9, 'right': 1}
size_hint: [1, 0.8]
canvas.before:
PushMatrix
Rotate:
angle: 0
origin: self.center
canvas.after:
PopMatrix
Line:
width: 2.
rectangle: (self.x + 40, self.y + 40, self.width/1.1, self.height/1.12)
ToggleButton:
id: show_bcode
pos_hint: {'bottom': 1, 'right': 1}
size_hint: [1, 0.1]
color: (1,1,1,1)
background_color: (0,0,0,0)
background_normal: ''
canvas.before:
Color:
rgba: (.18,.36,.61,1) if self.state=='down' else (0,0,0,1)
Rectangle:
pos: self.pos
size: self.size
text: 'Hier kom die barcode...'
''')
class BarcWin(FloatLayout):
cam_cam = ObjectProperty(None)
def __init__(self, **kwargs):
super(BarcWin, self).__init__(**kwargs)
self.cam_cam = ScanCamera()
def accept_in(self):
print('In')
def accept_out(self):
print('Out')
class ScanCamera(Image):
play = BooleanProperty(True)
index = NumericProperty(-1)
resolution = ListProperty([Window.width, Window.height])
symbols = ListProperty([])
code_types = ListProperty(set(pyzbar.pyzbar.ZBarSymbol))
Symb = namedtuple('Symb', ['type','data'])
app_ini_ = ObjectProperty(None)
got_bcode = BooleanProperty(False)
def __init__(self, **kwargs):
self._camera = None
super(ScanCamera, self).__init__(**kwargs)
if self.index == -1:
self.index = 0
on_index = self._on_index
fbind = self.fbind
fbind('index', on_index)
fbind('resolution', on_index)
on_index()
self.app_ini_ = App.get_running_app()
def on_tex(self, *l):
self.canvas.ask_update()
if not self.texture == None:
self.symbols = self._detect_qrcode_frame(texture=self.texture, code_types=self.code_types)
if not self.symbols == []:
for s in self.symbols:
if s.data:
if s.data.decode('utf-8') != "":
self.app_ini_.root.ids.show_bcode.text = s.data.decode('utf-8')
def _on_index(self, *largs):
self._camera = None
if self.index < 0:
return
if self.resolution[0] < 0 or self.resolution[1] < 0:
return
#first init of corecamera object
self._camera = CoreCamera(index=self.index,
resolution=self.resolution, stopped=True)
#when camera loads call _camera_loaded method to bind corecamera method with uix.image texture
self._camera.bind(on_load=self._camera_loaded)
if self.play:
self._camera.start()
self._camera.bind(on_texture=self.on_tex)
def _camera_loaded(self, *largs):
#bind camera texture with uix.image texture that is still equal to None
self.texture = self._camera.texture
def on_play(self, instance, value):
if not self._camera:
return
if value:
self._camera.start()
else:
self._camera.stop()
def _detect_qrcode_frame(self, texture, code_types):
if not self.got_bcode:
image_data = texture.pixels
size = texture.size
# Fix for mode mismatch between texture.colorfmt and data returned by
# texture.pixels. texture.pixels always returns RGBA, so that should
# be passed to PIL no matter what texture.colorfmt returns. refs:
# https://github.com/AndreMiras/garden.zbarcam/issues/41
pil_image = Img.frombytes(mode='RGBA', size=size,
data=image_data)
bcode = []
codes = pyzbar.pyzbar.decode(pil_image, symbols=code_types)
#print(pil_image, type(pil_image), dir(pil_image))
if codes != []:
for code in codes:
symbol = self.Symb(type=code.type, data=code.data)
bcode.append(symbol)
return bcode
else:
self.got_bcode = False
return []
class TestCamera(App):
title = 'Scan Camera'
def build(self):
return BarcWin()
def on_stop(self):
cc = ScanCamera()
print('Stop')
cc._camera.stop()
def on_pause(self):
return True
def on_resume(self):
pass
TestCamera().run()
I'm new to kivy , I'm trying to write an application using kivy in python, I got struck at one point where i have to read text from textinput whenever it is changed and based on that i want to implement my button's functionality - I have gone through all the documentation but i couldn't figure out how to do it - Can any body tell me how can I resolve this or am I missing something?
from __future__ import print_function
from kivy.app import App
from kivy.lang import Builder
from kivy.uix.boxlayout import BoxLayout
from kivy.core.image import Image
from kivy.uix.floatlayout import FloatLayout
from kivy.graphics import *
from kivy.uix.anchorlayout import AnchorLayout
from kivy.uix.button import Button
from kivy.uix.label import Label
from kivy.uix.textinput import TextInput
from kivy.uix.popup import Popup
from kivy.properties import ObjectProperty
import walascan
from kivy.clock import Clock
import os
kv = """
<KartScan>:
IntroScreen:
<IntroScreen#Screen>:
orientation: 'horizontal'
name: 'introscreen'
canvas.before:
Rectangle:
pos: self.pos
size: self.size
source: 'index.png'
AnchorLayout:
anchor_x: 'center'
anchor_y: 'center'
BoxLayout:
orientation:'horizontal'
size_hint: .5, .1
canvas:
Color:
rgb: 1, 1, 1
Rectangle:
pos: self.pos
size: self.size
spacing: 20
pos_hint: {'center_x':.8, 'center_y': .8}
AnchorLayout:
anchor_x: 'left'
size_hint_x: .5
TextInput:
id: waybill
width: 20
text: "Enter Waybill No."
multiline: False
height: self.minimum_height
size_hint_y: None
font_size: 30
focus: True
on_text_validate: app.on_waybill()
AnchorLayout:
anchor_x: 'right'
size_hint_x: None
Button:
size_hint: None, None
height: 50
width: self.texture_size[0]
padding: 10, 10
text: "Add"
on_press:app.buttonClicked()
on_release: root.current = 'mainpage'
AnchorLayout:
anchor_x: 'right'
size_hint_x: None
Button:
size_hint: None, None
height: 50
width: self.texture_size[0]
padding: 10, 10
text: "Compare"
on_press:app.buttonClicked()
on_release: root.current = 'mainpage'
"""
Builder.load_string(kv)
waybill = TextInput(text="Enter Waybill No.", multiline=False)
class KartScan(FloatLayout):
def __init__(self, **kwargs):
super(KartScan, self).__init__(**kwargs)
self.register_event_type('on_text_validate')
def on_text(self, *args):
print('new value is ', waybill.text)
def on_text_validate(self):
pass
def on_focus(self, obj, focused):
if not focused:
self.dispatch('on_text_validate')
class KartScanApp(App):
def build(self):
return KartScan()
def buttonClicked(self):
popup = Popup(title='Result',
content=Label(text=self.on_waybill()),
size_hint=(None, None), size=(100, 100))
popup.bind()
popup.open()
def getwlbtstate(self):
return walascan.mainAntennas()
def on_waybill(self):
waybill.bind(text=KartScan.on_text_validate)
# popup = Popup(title='Result',
# content=Label(text=waybill.text),
# size_hint=(None, None), size=(100, 100))
# popup.bind()
# popup.open()
return waybill.text
if __name__ == '__main__':
KartScanApp().run()
kv file
TextInput:
on_text: print(self.text)
You could use on_text to call a function when the text changes. I think it sometimes even triggers when no change has occured.
TextInput has a text property, and in kivy, all properties have associated on_xxx events, that you can bind to to react to them, so when reading the doc, even if it's not explicitly mentionned for them, everytime you see something is defined as a Property (or any subclass of it, like StringPropertyNumericProperty,ObjectProperty,AliasProperty`).
TextInput:
on_text: do_something(self.text)
or in python
t = TextInput(text='', on_text=do_something)
or
t = TextInput(text='')
t.bind(on_text=do_something)