I'm new with Python and I tried to sort out this problem, but unlikely I wasn't able to do this. Dropdown is dinamically populated via mqtt (here for instance is mosquito) and after the selection of a value I need to change Screen and when I return in the screen with the dropdown it should be empty.
Someone have some idea for doing it? Thank you in advance.
main.py
#-*-coding:utf8;-*-
#qpy:2
#qpy:kivy
#!/usr/bin/python
#@@@@@@ -*- coding: utf-8 -*-
from kivy.app import App
from kivy.uix.screenmanager import ScreenManager, Screen
from kivy.uix.dropdown import DropDown
from kivy.uix.button import Button
from kivy.core.window import Window
#from kivy.properties import DictProperty
import xmlrpclib
import calendar
import datetime
from urllib3.util.timeout import current_time
from datetime import date, time, timedelta
import locale
from kivy.uix.togglebutton import ToggleButton
from kivy.properties import ListProperty
from threading import Thread
import paho.mqtt.client as mqtt
import time
from time import sleep
from ConfigParser import SafeConfigParser
class CustomDropDownChip(DropDown):
def __init__(self, **kwargs):
super(CustomDropDownChip, self).__init__(**kwargs)
notes = chip_list
for note in notes:
btn = Button(text='%s' % note, size_hint_y=None, height=int(Window.height)/10)
btn.bind(on_release=lambda btn: self.select('CHIP: ' + btn.text))
self.add_widget(btn)
class StartScreen(Screen):
pass
class InsertBox(Screen):
global chip_list
chip_list = []
global chip_list_empty
chip_list_empty = []
global connected_flag
consommables = ListProperty([])
def buttons_down(self):
app = App.get_running_app()
app.chip_value = self.ids.id_chip.text
app.InsertSelection = 'InsertBoxConfirm'
def on_connect(self, mqttc, obj, flags, rc):
if rc==0:
mqttc.connected_flag=True
connected_flag = True
print("connected OK")
else:
print("Bad connection Returned code=",rc)
def on_disconnect(self, mqttc, obj, rc):
pass
def on_message(self, mqttc, obj, msg):
response = str(msg.payload)
if response not in chip_list:
sleep(1)
chip_list.append(response)
if mqttc.connected_flag == False:
mqttc.on_disconnect()
def on_publish(self, mqttc, obj, mid):
print("mid: "+str(mid))
def on_subscribe(self, mqttc, obj, mid, granted_qos):
print("Subscribed: "+str(mid)+" "+str(granted_qos))
def on_log(self, mqttc, obj, level, string):
print(string)
def __init__(self, **kwargs):
super(InsertBox, self).__init__(**kwargs)
def stop_mqtt(self):
mqttc.disconnect()
def start_mqtt(self):
self.read_chip()
def read_chip(self, *args):
global t
t = Thread(target=self.read_).start()
def read_(self):
mqtt.Client.connected_flag=False#create flag in class
connected_flag = False
global mqttc
mqttc = mqtt.Client(transport="websockets")
mqttc.on_message = self.on_message
mqttc.on_connect = self.on_connect
mqttc.on_publish = self.on_publish
mqttc.on_subscribe = self.on_subscribe
mqttc.on_log = self.on_log
mqttc.connect("test.mosquitto.org", 8080, 60)
mqttc.subscribe("temp/random", 0)
mqttc.loop_forever()
def consume(self, *args):
while self.consommables and time() < (Clock.get_time() + MAX_TIME):
item = self.consommables.pop(0) # i want the first one
label = Factory.MyLabel(text=item)
self.root.ids.id_chip.text = label #add_widget(label)
# @classmethod
def reset_chip_list(self):
chip_list = chip_list_empty
class InsertBoxConfirm(Screen):
def buttons_set(self):
InsertBox.buttons_set()
def buttons_reset(self):
InsertBox.buttons_reset()
class MyScreenManager(ScreenManager):
def SetChip(self, value):
pass
class testdropdownApp(App):
title = "Kivy Drop-Down List Demo"
chip_list = chip_list_empty
chip_value = ''
def build(self):
return MyScreenManager()
if __name__ == '__main__':
testdropdownApp().run()
testdropdown.kv
#:kivy 1.10.0
#:import Factory kivy.factory.Factory
<CustomDropDownChip>:
on_select:
app.root.ids.InsertBox.ids.id_chip.text = '{}'.format(args[1])
app.root.SetChip(args[1])
<StartScreen>:
name: 'StartScreen'
Button:
text: 'Start'
on_release:
root.manager.transition.direction = 'left'
root.manager.transition.duration = 0
root.manager.current = 'InsertBox'
<InsertBox>:
name: 'InsertBox'
id: test00
on_enter:
root.reset_chip_list()
root.start_mqtt()
on_leave:
root.stop_mqtt()
GridLayout:
rows: 2
id: test01
GridLayout:
rows: 1
size_hint_y: .27
padding: 5
Button:
id: id_chip
text: 'Select chip'
# size_hint_y: .5
spacing: 5
on_release: Factory.CustomDropDownChip().open(self)
GridLayout:
size_hint_y: .2
height: .15
cols: 2
BoxLayout:
padding: 5
orientation: 'horizontal'
size: root.size
pos: root.pos
spacing: 5
# height: .15
Button:
text: "Back"
on_press:
root.reset_chip_list()
root.manager.transition.direction = 'left'
root.manager.transition.duration = 0
root.manager.current = 'StartScreen'
Button:
text: 'OK'
on_press:
root.buttons_down()
root.manager.transition.direction = 'left'
root.manager.transition.duration = 0
root.manager.current = 'InsertBoxConfirm'
<InsertBoxConfirm>:
name: 'InsertBoxConfirm'
on_pre_enter:
id_chip_label.text = app.chip_value
GridLayout:
rows: 2
id: id_InsertBoxConfirm
GridLayout:
rows: 1
size_hint_y: .27
padding: 5
Label:
id: id_chip_label
text: 'valore CHIP'
GridLayout:
size_hint_y: .2
height: .15
cols: 1
BoxLayout:
padding: 5
orientation: 'horizontal'
size: root.size
pos: root.pos
spacing: 5
Button:
text: 'OK'
id: button_ok
on_press:
root.manager.transition.direction = 'left'
root.manager.transition.duration = 0
root.manager.current = 'InsertBox'
<MyScreenManager>:
StartScreen:
id: 'StartScreen'
name: 'StartScreen'
InsertBox:
id: InsertBox
name: 'InsertBox'
InsertBoxConfirm:
id: InsertBoxConfirm
name: 'InsertBoxConfirm'
Please refer to the overview, snippets, and example for details.
#:import Factory kivy.factory.Factory
root.reset_chip_list()
from on_enter:
to on_leave:
Factory.CustomDropDownChip().open(self)
with a new callbackmethod, root.create_open_customdropdown(self)
root.reset_chip_list()
from on_press:
Back Button because when we leave the screen, it will automatically fired on_leave:
event.app.chip_value
with root.manager.chip_value
because we will be moving variable, chip_value
from App class to root class. Button:
id: id_chip
text: 'Select chip'
spacing: 5
on_release:
root.create_open_customdropdown(self)
from kivy.properties import BooleanProperty, ObjectProperty
class InsertBox(Screen):
chip_list = []
with chip_list = ListProperty([])
; chip_list_empty = []
with chip_list_empty = ListProperty([])
; and add connected_flag = BooleanProperty(False)
dropdown = ObjectProperty(None)
at class level of class InsertBox(Screen):
so that we can use this to hook-up to the CustomDropDownChip object and remove it.class InsertBox(Screen):
chip_list
with self.chip_list
; chip_list_empty
with self.chip_list_empty
; connected_flag
with self.connected_flag
chip_list = chip_list_empty
from class testdropdownApp():
chip_value = ''
from class testdropdownApp()
to class MyScreenManager():
SetChip()
method, replace pass
with self.chip_value = value
chip_list
as arguments; remove notes = chip_list
; and replace notes
with chip_list
class CustomDropDownChip(DropDown):
def __init__(self, chip_list, **kwargs):
super(CustomDropDownChip, self).__init__(**kwargs)
for note in chip_list:
btn = Button(text='%s' % note, size_hint_y=None, height=int(Window.height)/10)
btn.bind(on_release=lambda btn: self.select('CHIP: ' + btn.text))
self.add_widget(btn)
...
class InsertBox(Screen):
consommables = ListProperty([])
chip_list = ListProperty([])
chip_list_empty = ListProperty([])
connected_flag = BooleanProperty(False)
dropdown = ObjectProperty(None)
def create_open_customdropdown(self, instance):
self.dropdown = CustomDropDownChip(self.chip_list)
self.dropdown.open(instance)
...
def reset_chip_list(self):
print("\tlen(chip_list)=", len(self.chip_list))
self.chip_list = self.chip_list_empty
print("\tlen(chip_list)=", len(self.chip_list))
if self.dropdown is not None:
self.remove_widget(self.dropdown)
from kivy.app import App
from kivy.uix.screenmanager import ScreenManager, Screen
from kivy.uix.dropdown import DropDown
from kivy.uix.button import Button
from kivy.core.window import Window
from datetime import time
from threading import Thread
import paho.mqtt.client as mqtt
import time
from time import sleep
from kivy.factory import Factory
from kivy.clock import Clock
from kivy.properties import BooleanProperty, ListProperty, ObjectProperty
MAX_TIME = 1/60.
class CustomDropDownChip(DropDown):
def __init__(self, chip_list, **kwargs):
super(CustomDropDownChip, self).__init__(**kwargs)
for note in chip_list:
btn = Button(text='%s' % note, size_hint_y=None, height=int(Window.height)/10)
btn.bind(on_release=lambda btn: self.select('CHIP: ' + btn.text))
self.add_widget(btn)
class StartScreen(Screen):
pass
class InsertBox(Screen):
consommables = ListProperty([])
chip_list = ListProperty([])
chip_list_empty = ListProperty([])
connected_flag = BooleanProperty(False)
dropdown = ObjectProperty(None)
def create_open_customdropdown(self, instance):
self.dropdown = CustomDropDownChip(self.chip_list)
self.dropdown.open(instance)
def buttons_down(self):
app = App.get_running_app()
app.InsertSelection = 'InsertBoxConfirm'
def on_connect(self, mqttc, obj, flags, rc):
if rc==0:
mqttc.connected_flag = True
self.connected_flag = True
print("connected OK")
else:
print("Bad connection Returned code=",rc)
def on_disconnect(self, mqttc, obj, rc):
pass
def on_message(self, mqttc, obj, msg):
response = str(msg.payload)
if response not in self.chip_list:
sleep(1)
self.chip_list.append(response)
if mqttc.connected_flag == False:
mqttc.on_disconnect()
def on_publish(self, mqttc, obj, mid):
print("mid: "+str(mid))
def on_subscribe(self, mqttc, obj, mid, granted_qos):
print("Subscribed: "+str(mid)+" "+str(granted_qos))
def on_log(self, mqttc, obj, level, string):
print(string)
def __init__(self, **kwargs):
super(InsertBox, self).__init__(**kwargs)
def stop_mqtt(self):
mqttc.disconnect()
def start_mqtt(self):
self.read_chip()
def read_chip(self, *args):
global t
t = Thread(target=self.read_).start()
def read_(self):
mqtt.Client.connected_flag = False # create flag in class
self.connected_flag = False
global mqttc
mqttc = mqtt.Client(transport="websockets")
mqttc.on_message = self.on_message
mqttc.on_connect = self.on_connect
mqttc.on_publish = self.on_publish
mqttc.on_subscribe = self.on_subscribe
mqttc.on_log = self.on_log
mqttc.connect("test.mosquitto.org", 8080, 60)
mqttc.subscribe("temp/random", 0)
mqttc.loop_forever()
def consume(self, *args):
while self.consommables and time() < (Clock.get_time() + MAX_TIME):
item = self.consommables.pop(0) # i want the first one
label = Factory.MyLabel(text=item)
self.root.ids.id_chip.text = label #add_widget(label)
# @classmethod
def reset_chip_list(self):
print("\tlen(chip_list)=", len(self.chip_list))
self.chip_list = self.chip_list_empty
print("\tlen(chip_list)=", len(self.chip_list))
if self.dropdown is not None:
self.remove_widget(self.dropdown)
class InsertBoxConfirm(Screen):
def buttons_set(self):
InsertBox.buttons_set()
def buttons_reset(self):
InsertBox.buttons_reset()
class MyScreenManager(ScreenManager):
chip_value = ''
def SetChip(self, value):
self.chip_value = value
class testdropdownApp(App):
title = "Kivy Drop-Down List Demo"
def build(self):
return MyScreenManager()
def on_stop(self):
self.root.ids.InsertBox.stop_mqtt()
if __name__ == '__main__':
testdropdownApp().run()
#:kivy 1.11.0
<CustomDropDownChip>:
on_select:
app.root.ids.InsertBox.ids.id_chip.text = '{}'.format(args[1])
app.root.SetChip(args[1])
<StartScreen>:
name: 'StartScreen'
Button:
text: 'Start'
on_release:
root.manager.transition.direction = 'left'
root.manager.transition.duration = 0
root.manager.current = 'InsertBox'
<InsertBox>:
name: 'InsertBox'
id: test00
on_enter:
root.start_mqtt()
on_leave:
root.stop_mqtt()
root.reset_chip_list()
GridLayout:
rows: 2
id: test01
GridLayout:
rows: 1
size_hint_y: .27
padding: 5
Button:
id: id_chip
text: 'Select chip'
# size_hint_y: .5
spacing: 5
on_release:
root.create_open_customdropdown(self)
GridLayout:
size_hint_y: .2
height: .15
cols: 2
BoxLayout:
padding: 5
orientation: 'horizontal'
size: root.size
pos: root.pos
spacing: 5
# height: .15
Button:
text: "Back"
on_press:
root.manager.transition.direction = 'left'
root.manager.transition.duration = 0
root.manager.current = 'StartScreen'
Button:
text: 'OK'
on_press:
root.buttons_down()
root.manager.transition.direction = 'left'
root.manager.transition.duration = 0
root.manager.current = 'InsertBoxConfirm'
<InsertBoxConfirm>:
name: 'InsertBoxConfirm'
on_pre_enter:
id_chip_label.text = root.manager.chip_value
GridLayout:
rows: 2
id: id_InsertBoxConfirm
GridLayout:
rows: 1
size_hint_y: .27
padding: 5
Label:
id: id_chip_label
text: 'valore CHIP'
GridLayout:
size_hint_y: .2
height: .15
cols: 1
BoxLayout:
padding: 5
orientation: 'horizontal'
size: root.size
pos: root.pos
spacing: 5
Button:
text: 'OK'
id: button_ok
on_press:
root.manager.transition.direction = 'left'
root.manager.transition.duration = 0
root.manager.current = 'InsertBox'
<MyScreenManager>:
StartScreen:
id: 'StartScreen'
name: 'StartScreen'
InsertBox:
id: InsertBox
name: 'InsertBox'
InsertBoxConfirm:
id: InsertBoxConfirm
name: 'InsertBoxConfirm'