从kivy下拉菜单中删除所有按钮

时间:2018-08-22 15:34:46

标签: python python-2.7 kivy kivy-language

我是Python的新手,我试图解决此问题,但不太可能无法做到这一点。 下拉菜单是通过mqtt(例如,此处是蚊子)动态填充的,选择了一个值后,我需要更改Screen,当我返回带有下拉菜单的屏幕时,它应该为空。

有人对此有想法吗? 预先谢谢你。

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'

2 个答案:

答案 0 :(得分:0)

您在这里:

for child in self.mydropdownsomething.children[:]:
    self.mydropdownsomething.remove_widget(child)

其中mydropdownsomething是动态添加下拉按钮的对象。

答案 1 :(得分:0)

有关详细信息,请参阅概述,摘要和示例。

概述

kv文件

  1. 删除导入语句#:import Factory kivy.factory.Factory
  2. root.reset_chip_list()on_enter:移到on_leave:
  3. 用新的回调方法Factory.CustomDropDownChip().open(self)代替root.create_open_customdropdown(self)
  4. root.reset_chip_list()后退按钮中删除on_press:,因为当我们离开屏幕时,它将自动触发on_leave:事件。
  5. app.chip_value替换root.manager.chip_value,因为我们将把chip_value变量从App类移到根类。

代码段-kv文件

            Button:
                id: id_chip
                text: 'Select chip'
                spacing: 5
                on_release:
                    root.create_open_customdropdown(self)

Python代码

  1. 添加导入语句from kivy.properties import BooleanProperty, ObjectProperty
  2. class InsertBox(Screen):删除变量(全局chip_list;全局chip_list_empty;全局connected_flag)
  3. chip_list = []替换为chip_list = ListProperty([])chip_list_empty = []chip_list_empty = ListProperty([]);并添加connected_flag = BooleanProperty(False)
  4. dropdown = ObjectProperty(None)类级别添加ObjectProperty class InsertBox(Screen):,以便我们可以使用它来连接 CustomDropDownChip 对象并将其删除。
  5. class InsertBox(Screen):内实施一个新方法create_open_customdropdown(self,instance):
  6. 在方法中,将chip_list替换为self.chip_listchip_list_emptyself.chip_list_emptyconnected_flagself.connected_flag
  7. chip_list = chip_list_empty移除class testdropdownApp():
  8. chip_value = ''class testdropdownApp()移到class MyScreenManager():
  9. SetChip()方法中,将pass替换为self.chip_value = value
  10. CustomDropDownChip 的构造函数中,添加chip_list作为参数;删除notes = chip_list;并将notes替换为chip_list

代码段-Python代码

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)

示例

main.py

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

testdropdown.kv

#: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'

输出

Img01 Img02 Img03 Img04