Update value in Kivy (Python) widget - python

I'd like to display numeric values coming from a sensor (Tinkerforge ambient light sensor) in Kivy widgets. Unfortunately the variable 'illuminance' doesn't seem to change at all and the widgets display '0'.'illuminance' seems to update nicely and gets printed on the console. What am I doing wrong?
import kivy
import random
from kivy.clock import Clock
from kivy.app import App
from kivy.uix.label import Label
from kivy.uix.boxlayout import BoxLayout
from tinkerforge.ip_connection import IPConnection
from tinkerforge.brick_dc import BrickDC
from tinkerforge.bricklet_ambient_light import BrickletAmbientLight
HOST = "localhost" # Tinkerforge IP and port
PORT = 4223
UID = "uM9" # sensor ID
illuminance = 0
ipcon = IPConnection() # Create IP connection
al = BrickletAmbientLight(UID, ipcon) # Create device object
ipcon.connect(HOST, PORT) # Connect to brickd
class TimerTink:
def tinker(self):
illuminance = al.get_illuminance() #read sensor value
print(illuminance)
class TinkerApp(App):
def build(self):
main_layout = BoxLayout(padding=10, orientation="vertical")
for i in range(2):
h_layout = BoxLayout(padding=10)
for i in range(2):
lbl = Label(text=str(illuminance),)
h_layout.add_widget(lbl)
main_layout.add_widget(h_layout)
event = Clock.schedule_interval(TimerTink.tinker, 1/2)
return main_layout
if __name__ == "__main__":
app = TinkerApp()
app.run()
Finally it's working, thanks to #YOSHI 's suggestions:
import kivy
import random
from kivy.clock import Clock
from kivy.app import App
from kivy.uix.label import Label
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.floatlayout import FloatLayout
from tinkerforge.ip_connection import IPConnection
from tinkerforge.brick_dc import BrickDC
from tinkerforge.bricklet_ambient_light import BrickletAmbientLight
HOST = "localhost" # Tinkerforge IP and port
PORT = 4223
UID = "uM9" # sensor ID
illuminance = 0
ipcon = IPConnection() # Create IP connection
al = BrickletAmbientLight(UID, ipcon) # Create device object
ipcon.connect(HOST, PORT) # Connect to brickd
class TinkerApp(App):
def build(self):
i = 0
main_layout = BoxLayout(padding=10, orientation="vertical")
h_layout = FloatLayout(size=(300,300))
self.label = Label(text=str(illuminance),pos=(i*100, i*100),size_hint = (.1,.1))
h_layout.add_widget(self.label)
main_layout.add_widget(h_layout)
Clock.schedule_interval(self.timer, 0.1)
return main_layout
def timer(self, dt):
illuminance = al.get_illuminance() #read sensor value
self.label.text = str(illuminance)
print(str(illuminance))
if __name__ == "__main__":
app = TinkerApp()
app.run()

The function 'tinker' in the TimeTink class takes 2 arguments: self and dt
def tinker(self,dt):
illuminance = al.get_illuminance() #read sensor value
print(illuminance)
or you change the line where you call the method to sth. like this:
event = Clock.schedule_interval(lambda dt: TimerTink.tinker, 1/2)
for more info visit the doc for kivy.clock.
Edit: (maybe this works)
import kivy
import random
from kivy.clock import Clock
from kivy.app import App
from kivy.uix.label import Label
from kivy.uix.boxlayout import BoxLayout
from tinkerforge.ip_connection import IPConnection
from tinkerforge.brick_dc import BrickDC
from tinkerforge.bricklet_ambient_light import BrickletAmbientLight
HOST = "localhost" # Tinkerforge IP and port
PORT = 4223
UID = "uM9" # sensor ID
illuminance = 0
ipcon = IPConnection() # Create IP connection
al = BrickletAmbientLight(UID, ipcon) # Create device object
ipcon.connect(HOST, PORT) # Connect to brickd
main_layout = BoxLayout(padding=10, orientation="vertical")
for i in range(2):
h_layout = BoxLayout(padding=10)
for i in range(2):
lbl = Label(text=str(illuminance),)
h_layout.add_widget(lbl)
main_layout.add_widget(h_layout)
def tinker(self):
illuminance = al.get_illuminance() #read sensor value
lbl.text = str(illuminance)
print(illuminance)
class TinkerApp(App):
def build(self):
event = Clock.schedule_interval(tinker, 1/2)
return main_layout
if __name__ == "__main__":
app = TinkerApp()
app.run()

Related

Kivy Ui Freezing .I have Written a Simple YouTube downloader .But When i press Button Ui Got Freezing Till download Complete

from multiprocessing.sharedctypes import Value
from pytube import YouTube
import kivy from kivy.app
import App from kivy.uix.label
import Label from kivy.uix.gridlayout
import GridLayout from kivy.uix.button
import Button from kivy.uix.textinput import TextInput
import threading
class grid_layout (GridLayout):
def __init__(self, **kwargs):
super().__init__( **kwargs)
self.tx1 = TextInput(text = 'Enter A Youtube Link',size_hint = (0.8,0.9) , pos = (400,500),size = (500,100))
self.add_widget(self.tx1)
self.bt2 = Button(text = "Exit ",font_size = '20sp',bold = True, size_hint = (0.6,0.6),pos = (600,200))
self.add_widget(self.bt2)
self.bt1 = Button(text = 'Download',font_size = '20sp',
bold = True,
italic = True,size_hint = (0.6,0.6) ,
pos = (400,200),on_press = self.download
)
self.add_widget(self.bt1)
def download(self,obj):
link = str(self.tx1.text)
download = YouTube(link)
print('Processing The Video.Please Wait Depends Upon Size And Your Net Speed Download Depends')
task = download.streams.filter(res = '360p',file_extension='mp4')
started = download.streams.get_by_itag(22)
started.download()
print('Download Completed') class MyApp(App):
def build (self):
return grid_layout()
if __name__ == '__main__':
MyApp().run()

kivy app dont sending data in the background (when screen is off)

Kivy service app dont send any data to mysql when screen is off
Trying write simple app with kivy python which should run the service when you press the button.
Service must track gps location (using plyer) and sending Name (from label) Lat Lon (from on_gps_location) and date from var datetime to mysql db. Its actualy working pretty well when you using app or switched it to another app. But when u turning off phone screen service dont stop cause i see the notification about service is running but no one new data dont sending anymore.
Note: im testing it with difference phones, its actually working on any phones but not on my (HONOR 30i)
Note2: When u select "traffic stat" on your phone it calls that your app spent for example 30mb when u using app and 0mb in background.
There my main.py code:
from kivy.app import App
from kivy.uix.button import Button
from kivy.config import Config
from plyer import gps
from kivy.uix.gridlayout import GridLayout
from kivy.uix.label import Label
from kivy.uix.textinput import TextInput
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.anchorlayout import AnchorLayout
import mysql.connector
import android
from mysql.connector import errorcode
from datetime import datetime
from kivy.utils import platform
from kivy.clock import Clock
import time
from jnius import autoclass
from android import AndroidService
from kivy.storage.jsonstore import JsonStore
from threading import Thread
store = JsonStore('hello.json')
class MyApp(App):
def request_android_permissions(self):
from android.permissions import request_permissions, Permission
def callback(permissions, results):
if all([res for res in results]):
print('callback. All permissions granted.')
else:
print('callback. Some permissions refused.')
request_permissions([Permission.ACCESS_COARSE_LOCATION, Permission.ACCESS_FINE_LOCATION, Permission.ACCESS_BACKGROUND_LOCATION, Permission.WRITE_EXTERNAL_STORAGE], callback)
def build(self):
if platform == 'android':
print('Requesting permissions')
self.request_android_permissions()
print('App is running')
if len(store) == 0:
al = AnchorLayout()
bl = BoxLayout(orientation = 'vertical', size_hint=[None,None], size = [500,300])
self.lbl1 = Label(text = 'Put your name here')
bl.add_widget(self.lbl1)
self.txt1 = TextInput(text = '', multiline = False)
bl.add_widget(self.txt1)
bl.add_widget(Button(text = 'Start', on_press = self.btn_press_start))
al.add_widget(bl)
return al
else:
al = AnchorLayout()
bl = BoxLayout(orientation = 'vertical', size_hint = [None, None], size = [500,300])
self.lbl1 = Label(text = 'Hello ' + store.get('Name')['name'])
bl.add_widget(self.lbl1)
bl.add_widget(Button(text = 'Start', on_press = self.btn_press_start))
al.add_widget(bl)
return al
def btn_press_start(self, instance):
global name
if len(store) == 0:
if instance.text == 'Start':
if self.txt1.text != '':
self.lbl1.text = 'Hello ' + self.txt1.text
store.put('Name', name = self.txt1.text)
print('Beggin')
name = self.txt1.text
self.start_service()
instance.text = 'Stop'
else:
self.lbl1.text = 'Write smth there!'
else:
#gps.stop()
self.service.stop()
print('Service stop')
self.txt1.text = ''
instance.text = 'Start'
else:
if instance.text == 'Start':
name = store.get('Name')['name']
self.start_service()
instance.text = 'Stop'
else:
self.service.stop()
print('Service stop')
instance.text = 'Start'
def start_service(self):
self.service = AndroidService('Service example', 'service is running')
self.service.start(name)
if name == "main":
MyApp().run()
and my service/main.py code:
import os
from os import environ
from kivy.app import App
from kivy.uix.button import Button
from kivy.config import Config
from plyer import gps
from kivy.uix.gridlayout import GridLayout
from kivy.uix.label import Label
from kivy.uix.textinput import TextInput
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.anchorlayout import AnchorLayout
import mysql.connector
import android
from mysql.connector import errorcode
from datetime import datetime
from kivy.utils import platform
from kivy.clock import Clock
import time
from jnius import autoclass
from android import AndroidService
print('SERVICE ON')
arg = environ.get('PYTHON_SERVICE_ARGUMENT', '')
def main():
gps.configure(on_location = on_gps_location)
print('Configure succes')
gps.start(minTime = 2000, minDistance = 0)
print('Going on')
time.sleep(10)
gps.stop()
print('BEFORE REPEAT')
config = {
'user': '', //I CLEAR THIS FIELDS//
'password': '',
'host': '',
'database': '',
'raise_on_warnings': True
}
db = mysql.connector.connect(**config)
cursor = db.cursor()
cur_time = datetime.now()
now = cur_time.strftime("%Y-%m-%d %H:%M:%S")
data_coord = {
'name' : arg,
'c1' : lat,
'c2' : lon,
'time': now,
}
add_coordinate = ("INSERT INTO //YOURDATABASE// (Name, Latitude, Longtitude, Date) VALUES (%(name)s, %(c1)s, %(c2)s, %(time)s)")
cursor.execute(add_coordinate, data_coord)
print('DATABASE UPDATE')
db.commit()
db.close()
def on_gps_location(**kwargs):
global lat
global lon
lat = kwargs['lat']
lon = kwargs['lon']
if __name__ == '__main__':
while True:
main()
time.sleep(20)

Create app folder after installing KivyMD apk file and read txt file from the folder

Please I have created a kivymd app and it's running well on my android device. The app reads the names from a txt file, randomise them and group them into preferred number of groups. It works fine but I want to add functionality that users can add their own txt file into a folder created by the app after installation so that the app will read the txt file from the root folder.
Now I need a way that the app can create the folder by itself after installation. And also how the app can read txt files from that folder for the grouping.
Thanks in advance
import random
import kivymd
from kivy.animation import Animation
from kivy.app import App
from kivy.factory import Factory
from kivy.graphics.context import Clock
from kivy.uix.popup import Popup
from kivy.uix.scrollview import ScrollView
from kivy.utils import get_color_from_hex
from kivymd.app import MDApp
from kivy.properties import StringProperty
from kivy.uix.boxlayout import BoxLayout
from kivy.core.window import Window
from kivy.lang.builder import Builder
from kivy.properties import NumericProperty
from kivy.uix.screenmanager import Screen
from kivymd.uix.card import MDCard
from kivymd.uix.label import MDLabel
from kivymd.uix.list import OneLineListItem
Window.fullscreen = True
Window.maximize()
class CardOn(MDCard):
pass
class ListItems(OneLineListItem):
text = StringProperty()
class ContentNavigationDrawer(BoxLayout):
pass
class NavigationDrawerIconButton(BoxLayout):
pass
class NavigationLayout(Screen):
state = ''
my_text = "No names loaded yet"
convert_to_string = "No names loaded yet"
raw_file = open("Name.txt", "r")
read_content = raw_file.read()
class_split = read_content.split("\n")
num_of_generated_groups = StringProperty()
Shuffled_list = []
grouping_critera = StringProperty()
student_total = 0
Groups = NumericProperty(1)
hint = StringProperty()
Randomized_list = []
Created_groups = []
refined_group = StringProperty(""" """)
students_to_string = StringProperty("No names loaded yet")
my_index = NumericProperty
new_titles = StringProperty()
def group_criteria(self, value):
self.grouping_critera = value
if self.grouping_critera == "Number of groups":
self.hint = "Select desired number of groups"
elif self.grouping_critera == "Number of groups":
self.grouping_critera = "Number of groups"
else:
self.hint = "Select desired students per groups"
print(self.grouping_critera)
def group_nums(self, value):
self.Groups = int(value)
print(self.Groups)
def read_names(self):
raw_file = open("Name.txt", "r")
read_content = raw_file.read()
self.class_split = read_content.split("\n")
def create_groups(self):
self.student_total = len(self.class_split)
self.Shuffled_list = self.class_split
random.shuffle(self.Shuffled_list)
self.Groups = int(self.Groups)
if self.grouping_critera == "Number of groups":
groups_to_students = round(self.student_total / self.Groups)
self.Created_groups = [self.Shuffled_list[i * groups_to_students:(i + 1) * groups_to_students] for i in
range((len(self.Shuffled_list) + groups_to_students - 1) // groups_to_students)]
else:
self.Created_groups = [self.Shuffled_list[i * self.Groups:(i + 1) * self.Groups] for i in
range((len(self.Shuffled_list) + self.Groups - 1) // self.Groups)]
print(f"Created groups are {self.Created_groups}")
for self.i in self.Created_groups:
card = MDCard(orientation="vertical", padding="8dp", size_hint=(None, None),
size=(self.width, "10dp"),
pos_hint={"center_x": .5, "center_y": .5})
self.ids.md_list.add_widget(card)
self.num_of_generated_groups = f"{len(self.Created_groups)} Groups Generated"
self.my_index = self.Created_groups.index(self.i) + 1 # the 1 will replace the index at 0
label = MDLabel(text=f"Group {self.my_index} members = {len(self.i)} ", theme_text_color="Custom",
text_color=(1, 1, 1, 1), halign="center", font_size=30)
self.ids.md_list.add_widget(label)
for e in self.i:
self.ids.md_list.add_widget(ListItems(text=e))
def clear_screen(self):
self.ids.md_list.clear_widgets()
def generate_groups(self):
self.clear_screen()
self.create_groups()
class GroupingApp(MDApp):
def __init__(self, **kwargs):
super().__init__(**kwargs)
self.screen = Builder.load_string(screen_helper)
def build(self):
return self.screen
if __name__ == '__main__':
GroupingApp().run()

Download Progress bar in Kivy

I am trying to build an app that downloads a file, whose progress can be tracked on a kivy app.
I have looked at the example here and here for the download progress.
This is my code:
from kivy.app import App
from kivy.uix.button import Button
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.label import Label
from kivy.uix.textinput import TextInput
from kivy.uix.popup import Popup
from kivy.factory import Factory
from kivy.properties import ObjectProperty
from kivy.clock import Clock
import urllib
URL = "http://s9.videozoo.me/S/saenai_heroine_no_sodatekata_flat_-_11.mp4?st=Ow7pwXbRt6vPWE-kr5Sn1A&e=1498847899&start=0"
class PopupBox(Popup):
pop_up_text = ObjectProperty()
def update_pop_up_text(self, p_message):
self.pop_up_text.text = p_message
class MyApp(App):
# layout
def show_popup(self):
self.pop_up = Factory.PopupBox()
self.pop_up.update_pop_up_text('Running some task...')
self.pop_up.open()
def build(self):
layout = BoxLayout(padding=10, orientation='vertical')
btn1 = Button(text="OK")
btn1.bind(on_press=self.buttonClicked)
layout.add_widget(btn1)
self.lbl1 = Label(text="test")
layout.add_widget(self.lbl1)
self.txt1 = TextInput(text='', multiline=False)
layout.add_widget(self.txt1)
return layout
# button click function
def buttonClicked(self, btn):
self.lbl1.text = "You wrote " + self.txt1.text
self.show_popup()
self.download_file(URL)
self.pop_up.dismiss()
def download_file(self, url):
u = urllib.request.urlopen(url)
meta = u.info()
metaInfo = str(meta).split()
fileTotalbytes = int(metaInfo[46])
data_blocks = []
total = 0
while True:
block = u.read(1024)
data_blocks.append(block)
total += len(block)
hash = ((60 * total) // fileTotalbytes)
print("[{}{}] {}%".format('#' * hash, ' ' * (60 - hash), int(total / fileTotalbytes * 100)), end="\r")
if not len(block):
break
data = b''.join(data_blocks) # had to add b because I was joining bytes not strings
u.close()
# run app
if __name__ == "__main__":
MyApp().run()
However, I am confused as to how do I bind the download_file function with the kivy widget functionality so as to make it work. How do I appropriately modify the print function so as to make it work with the widget
If you block in the mainthread kivy can no longer update the GUI. Instead create a new thread and use the #mainthread annotation to do gui updates.
Instead of the print you have to manipulate kivy widgets. You could create a rectangle and increase the width to 100%. You could create a textinput and output your text there.

twisted: flush data after a global value is updated

I am working with a chat app and I would like the server to control to flush the data to clients or not by pressing a button. I tried to do that by updating a global variable to trigger a if statement that can flush the data. However it seems that even the global variable is updated, it still does not trigger the if statement as the debugging "print" is not working, how can i fix that?
Here is the code
import kivy
from kivy.app import App
from kivy.uix.label import Label
from kivy.uix.scatter import Scatter
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.scrollview import ScrollView
from kivy.uix.button import Button
from kivy.graphics.vertex_instructions import Rectangle
from kivy.graphics.context_instructions import Color
from kivy.graphics.instructions import Instruction
from kivy.base import runTouchApp
from kivy.lang import Builder
import socket
from kivy.core.window import Window
import pygame
import random
from kivy.support import install_twisted_reactor
install_twisted_reactor()
from twisted.internet import reactor, protocol, defer
from twisted.protocols.basic import LineReceiver
from twisted.internet.protocol import Protocol, Factory
censored = 0
class MultiClientEcho(protocol.Protocol):
def __init__(self, factory, app):
self.factory = factory
self.app = app
def connectionMade(self):
self.factory.clients.append(self)
def dataReceived(self, data):
for client in self.factory.clients:
storedmessage = self.factory.app.handle_message(data)
global censored
if censored ==1:
print "send message"
client.transport.write(storedmessage)
elif censored ==2:
print "banned message"
client.transport.write("censored")
def connectionLost(self,reason):
self.factory.clients.remove(self)
class MultiClientEchoFactory(protocol.Factory):
protocol = MultiClientEcho
def __init__(self,app):
self.clients = []
self.app = app
def buildProtocol(self, addr):
return MultiClientEcho(self, self.app)
class ServerApp(App):
def build(self):
self.label = Label(text="server started\n")
self.approve_btn = Button(text="approve")
self.approve_btn.bind(on_release=self.send_message)
self.banned_btn = Button(text="banned")
self.banned_btn.bind(on_release=self.banned_message)
self.layout = BoxLayout(orientation='vertical', spacing=10)
reactor.listenTCP(8000, MultiClientEchoFactory(self))
self.layout.add_widget(self.label)
self.layout.add_widget(self.approve_btn)
self.layout.add_widget(self.banned_btn)
return self.layout
def send_message(self, *args):
global censored
censored = 1
self.label.text += "sent\n"
print censored
return censored
def banned_message(self, *args):
global censored
censored = 2
self.label.text += "censored\n"
print censored
return censored
def handle_message(self, msg):
self.label.text += "received: %s\n" % msg
return msg
if __name__ == '__main__':
ServerApp().run()

Categories