Python 在Kivy中实现计时器时遇到问题

Python 在Kivy中实现计时器时遇到问题,python,kivy,kivy-language,Python,Kivy,Kivy Language,我正在尝试创建一个kivy应用程序。 该应用程序的工作原理如下: 我通过MQTT在主题“tafelxuren”(x是一个介于1和8之间的数字)上发送我希望计时器持续的秒数 在发送了我希望它持续的秒数之后,我使用命令“start”向主题“tafelxstart”(x是一个介于1和8之间的数字)发送第二个MQTT命令 发送start命令后,我的计时器开始运行 在我的计时器下有3个按钮,暂停、继续和停止。 当使用MQTT命令启动和暂停计时器时,我似乎无法使我的恢复按钮正常工作,如果单击暂停按钮后还有

我正在尝试创建一个kivy应用程序。 该应用程序的工作原理如下:

  • 我通过MQTT在主题“tafelxuren”(x是一个介于1和8之间的数字)上发送我希望计时器持续的秒数
  • 在发送了我希望它持续的秒数之后,我使用命令“start”向主题“tafelxstart”(x是一个介于1和8之间的数字)发送第二个MQTT命令
  • 发送start命令后,我的计时器开始运行
  • 在我的计时器下有3个按钮,暂停、继续和停止。 当使用MQTT命令启动和暂停计时器时,我似乎无法使我的恢复按钮正常工作,如果单击暂停按钮后还有26秒,我希望计时器从该点恢复。相反,它从头开始

    My main.py:

    import os
    if os.name == 'posix':
        os.environ['KIVY_GL_BACKEND'] = 'gl'
    import kivy, time,threading
    from kivy.app import App
    from kivy.uix.gridlayout import GridLayout
    from kivy.uix.boxlayout import BoxLayout
    from kivy.uix.label import Label
    from kivy.uix.widget import Widget
    from kivy.properties import NumericProperty, ObjectProperty
    from kivy.clock import Clock
    from kivy.config import Config
    import paho.mqtt.client as mqtt
    Config.set('graphics', 'fullscreen', 'auto')
    import paho.mqtt.publish as publish
    import paho.mqtt.subscribe as subscribe
    import config
    
    # lege MQTT-client instantie
    client = None
    # De topics die gebruikt worden
    ingesteldetijd = [config.timeTopics['tafel1'],config.timeTopics['tafel2'],config.timeTopics['tafel3'],config.timeTopics['tafel4'],config.timeTopics['tafel5'],config.timeTopics['tafel6'],config.timeTopics['tafel7'],config.timeTopics['tafel8']]
    ingesteldetijdTopics = [config.tim1, config.tim2, config.tim3, config.tim4, config.tim5, config.tim6, config.tim7, config.tim8]
    
    starttopics = [config.startTopics['tafel1'],config.startTopics['tafel2'],config.startTopics['tafel3'],config.startTopics['tafel4'],config.startTopics['tafel5'],config.startTopics['tafel6'],config.startTopics['tafel7'],config.startTopics['tafel8']]
    def on_connect(client,userdata,flags,rc):
            '''
            This function gets triggered when MQTT is connected succesfully
            '''
            if(rc == 0):
                print("[INFO   ] [MQTT        ] MQTT connected to broker "+config.settings['broker']+".")
                client.subscribe('#')
                ##################################### ingestelde tijd subscriptions #####################################
                for x in range(0,8):
                    client.subscribe(ingesteldetijd[x])
                    print('[INFO   ] [MQTT        ] Subscribed to '+ingesteldetijd[x])
                ##################################### ingestelde tijd subscriptions #####################################
    
                ##################################### start topic subscriptions #####################################
                for x in range(0,8):
                    client.subscribe(starttopics[x])
                    print('[INFO   ] [MQTT        ] Subscribed to '+starttopics[x])
                ##################################### start topic subscriptions #####################################
            else:
                print("MQTT connection to broker "+config.settings['broker']+"failed.")
    
    
    def on_message(client,userdata,msg):
        '''
        If there's a message received on one of the topics, the messages gets handled here.
        '''
        ################################## tijd instellen topic ##################################
        if msg.topic == 'tafel1uren':
            config.tim1 = int(msg.payload.decode('utf-8'))
        if msg.topic == 'tafel2uren':
            config.tim2 = int(msg.payload.decode('utf-8'))
        if msg.topic == 'tafel3uren':
            config.tim3 = int(msg.payload.decode('utf-8'))
        if msg.topic == 'tafel4uren':
            config.tim4 = int(msg.payload.decode('utf-8'))
        if msg.topic == 'tafel5uren':
            config.tim5 = int(msg.payload.decode('utf-8'))
        if msg.topic == 'tafel6uren':
            config.tim6 = int(msg.payload.decode('utf-8'))
        if msg.topic == 'tafel7uren':
            config.tim7 = int(msg.payload.decode('utf-8'))
        if msg.topic == 'tafel8uren':
            config.tim8 = int(msg.payload.decode('utf-8'))
        ################################## tijd instellen topic ##################################
    
        if msg.topic == config.startTopics['tafel1']:
            if msg.payload.decode('utf-8') == 'start':
                config.tb1start = True
            if msg.payload.decode('utf-8') == 'stop':
                config.tb1start = False
        if msg.topic == config.startTopics['tafel2']:
            if msg.payload.decode('utf-8') == 'start':
                config.tb2start = True
            if msg.payload.decode('utf-8') == 'stop':
                config.tb2start = False
        if msg.topic == config.startTopics['tafel3']:
            if msg.payload.decode('utf-8') == 'start':
                config.tb3start = True
            if msg.payload.decode('utf-8') == 'stop':
                config.tb3start = False
        if msg.topic == config.startTopics['tafel4']:
            if msg.payload.decode('utf-8') == 'start':
                config.tb4start = True
            if msg.payload.decode('utf-8') == 'stop':
                config.tb4start = False
        if msg.topic == config.startTopics['tafel5']:
            if msg.payload.decode('utf-8') == 'start':
                config.tb5start = True
            if msg.payload.decode('utf-8') == 'stop':
                config.tb5start = False
        if msg.topic == config.startTopics['tafel6']:
            if msg.payload.decode('utf-8') == 'start':
                config.tb6start = True
            if msg.payload.decode('utf-8') == 'stop':
                config.tb6start = False
        if msg.topic == config.startTopics['tafel7']:
            if msg.payload.decode('utf-8') == 'start':
                config.tb7start = True
            if msg.payload.decode('utf-8') == 'stop':
                config.tb7start = False
        if msg.topic == config.startTopics['tafel8']:
            if msg.payload.decode('utf-8') == 'start':
                config.tb8start = True
            if msg.payload.decode('utf-8') == 'stop':
                config.tb8start = False
    
    class CrudeTimerGrid(GridLayout):
        _python_access = ObjectProperty(None)
        time = NumericProperty(0)
        def __init__(self,**kwargs):
            super(CrudeTimerGrid,self).__init__(**kwargs)
            self.runningTimer = 0
            Clock.schedule_interval(self.load_times,1)
            Clock.schedule_interval(self.start,1)
    
        def load_times(self, *_):
            tafelobjecten = self.parent.parent.ids
            for x in range(0,8):
                if list(tafelobjecten.values())[x] == self:
                    if str(list(tafelobjecten.keys())[x]) == 'tafel1':
                        self.time = config.tim1
                    if str(list(tafelobjecten.keys())[x]) == 'tafel2':
                        self.time = config.tim2
                    if str(list(tafelobjecten.keys())[x]) == 'tafel3':
                        self.time = config.tim3
                    if str(list(tafelobjecten.keys())[x]) == 'tafel4':
                        self.time = config.tim4
                    if str(list(tafelobjecten.keys())[x]) == 'tafel5':
                        self.time = config.tim5
                    if str(list(tafelobjecten.keys())[x]) == 'tafel6':
                        self.time = config.tim6
                    if str(list(tafelobjecten.keys())[x]) == 'tafel7':
                        self.time = config.tim7
                    if str(list(tafelobjecten.keys())[x]) == 'tafel8':
                        self.time = config.tim8
    
        def start(self, *_):
            tafelobjecten = self.parent.parent.ids
            self.runningTimer = self.time
            for x in range(0,8):
                if list(tafelobjecten.values())[x] == self:
                    if str(list(tafelobjecten.keys())[x]) == 'tafel1':
                        #self.time = config.tim1
                        if config.tb1start == True:
                            if(self.runningTimer > 0):
                                Clock.schedule_interval(self.tick,1)
                    elif str(list(tafelobjecten.keys())[x]) == 'tafel2':
                        #self.time = config.tim2
                        if config.tb2start == True:
                            if(self.runningTimer > 0):
                                Clock.schedule_interval(self.tick,1)
                    elif str(list(tafelobjecten.keys())[x]) == 'tafel3':
                        #self.time = config.tim3
                        if config.tb3start == True:
                            if(self.runningTimer > 0):
                                Clock.schedule_interval(self.tick,1)
                    elif str(list(tafelobjecten.keys())[x]) == 'tafel4':
                        #self.time = config.tim4
                        if config.tb4start == True:
                            if(self.runningTimer > 0):
                                Clock.schedule_interval(self.tick,1)
                    elif str(list(tafelobjecten.keys())[x]) == 'tafel5':
                        #self.time = config.tim5
                        if config.tb5start == True:
                            if(self.runningTimer > 0):
                                Clock.schedule_interval(self.tick,1)
                    elif str(list(tafelobjecten.keys())[x]) == 'tafel6':
                        #self.time = config.tim6
                        if config.tb6start == True:
                            if(self.runningTimer > 0):
                                Clock.schedule_interval(self.tick,1)
                    elif str(list(tafelobjecten.keys())[x]) == 'tafel7':
                        #self.time = config.tim7
                        if config.tb7start == True:
                            if(self.runningTimer > 0):
                                Clock.schedule_interval(self.tick,1)
                    elif str(list(tafelobjecten.keys())[x]) == 'tafel8':
                        #self.time = config.tim8
                        if config.tb8start == True:
                            if(self.runningTimer > 0):
                                Clock.schedule_interval(self.tick,1)
    
        def pause(self):
            tafelobjecten = self.parent.parent.ids
            for x in range(0,8):
                if list(tafelobjecten.values())[x] == self:
                    if str(list(tafelobjecten.keys())[x]) == 'tafel1':
                        config.tb1start = False
                        Clock.unschedule(self.tick)
                    if str(list(tafelobjecten.keys())[x]) == 'tafel2':
                        config.tb2start = False
                        Clock.unschedule(self.tick)
                    if str(list(tafelobjecten.keys())[x]) == 'tafel3':
                        config.tb3start = False
                        Clock.unschedule(self.tick)
                    if str(list(tafelobjecten.keys())[x]) == 'tafel4':
                        config.tb4start = False
                        Clock.unschedule(self.tick)
                    if str(list(tafelobjecten.keys())[x]) == 'tafel5':
                        config.tb5start = False
                        Clock.unschedule(self.tick)
                    if str(list(tafelobjecten.keys())[x]) == 'tafel6':
                        config.tb6start = False
                        Clock.unschedule(self.tick)
                    if str(list(tafelobjecten.keys())[x]) == 'tafel7':
                        config.tb7start = False
                        Clock.unschedule(self.tick)
                    if str(list(tafelobjecten.keys())[x]) == 'tafel8':
                        config.tb8start = False
                        Clock.unschedule(self.tick)
    
    
        def resume(self, *_):
            tafelobjecten = self.parent.parent.ids
            for x in range(0,8):
                if list(tafelobjecten.values())[x] == self:
                    if str(list(tafelobjecten.keys())[x]) == 'tafel1':
                        config.tb1start = True
                        Clock.schedule_interval(self.tick,1)
                    if str(list(tafelobjecten.keys())[x]) == 'tafel2':
                        config.tb2start = True
                        Clock.schedule_interval(self.tick,1)
                    if str(list(tafelobjecten.keys())[x]) == 'tafel3':
                        config.tb3start = True
                        Clock.schedule_interval(self.tick,1)
                    if str(list(tafelobjecten.keys())[x]) == 'tafel4':
                        config.tb4start = True
                        Clock.schedule_interval(self.tick,1)
                    if str(list(tafelobjecten.keys())[x]) == 'tafel5':
                        config.tb5start = True
                        Clock.schedule_interval(self.tick,1)
                    if str(list(tafelobjecten.keys())[x]) == 'tafel6':
                        config.tb6start = True
                        Clock.schedule_interval(self.tick,1)
                    if str(list(tafelobjecten.keys())[x]) == 'tafel7':
                        config.tb7start = True
                        Clock.schedule_interval(self.tick,1)
                    if str(list(tafelobjecten.keys())[x]) == 'tafel8':
                        config.tb8start = True
                        Clock.schedule_interval(self.tick,1)        #pass
    
        def stop(self, *_):
            #TODO: implement stop button
            pass
    
        def tick(self, *_):
            tafelobjecten = self.parent.parent.ids
            if self.runningTimer > 0:
                self.runningTimer -= 1
                # publish de juiste tafel topic met de waarde van de restrerende tijd
                for x in range(0,8):
                    if list(tafelobjecten.values())[x] == self:
                        client.publish(topic = str(list(tafelobjecten.keys())[x]), payload = str(self.runningTimer))
                        self.ids.Changelabel.text = str(time.strftime('%H:%M:%S',time.gmtime(self.runningTimer)))
            else:
                pass
    
    class Main(GridLayout):
        pass
    
    class CrudeTimerApp(App):
        pass
    
    if __name__ == '__main__':  
        client = mqtt.Client()
        client.on_connect = on_connect
        client.on_message = on_message
        client.username_pw_set(config.settings['username'], config.settings['password'])
        client.connect(config.settings['broker'])
        t = threading.Thread(target=client.loop_start())
        t.daemon = True
        t.start()
        CrudeTimerApp().run()
    
    我的.kv文件:

    #:kivy 1.10.1
    ################################### Widget template ##########################################
    <CrudeTimerGrid>:
        _python_access: Changelabel
        id: timer
        rows: 4
        BoxLayout:
            size_hint_y: 0.15
            orientation: 'horizontal'
            canvas.before:
                Color:
                    rgba: .5, .5, .5, 1
                Line:
                    width: 2
                    rectangle: self.x, self.y, self.width, self.height
            Label:
                font_size: 20
                text: 'Restrerende tijd:'
                canvas.before:
                    Color:
                        rgba: .5, .5, .5, 1
                    Line:
                        width: 2
                        rectangle: self.x, self.y, self.width, self.height
            Label:
                font_size: 20
                id: Changelabel
                canvas.before:
                    Color:
                        rgba: .5, .5, .5, 1
                    Line:
                        width: 2
                        rectangle: self.x, self.y, self.width, self.height
        BoxLayout:
            size_hint_y: 0.15
            orientation: 'horizontal'
            canvas.before:
                Color:
                    rgba: .5, .5, .5, 1
                Line:
                    width: 2
                    rectangle: self.x, self.y, self.width, self.height
            Label:
                font_size: 20
                text: 'Pauzetijd:'
                canvas.before:
                    Color:
                        rgba: .5, .5, .5, 1
                    Line:
                        width: 2
                        rectangle: self.x, self.y, self.width, self.height
            Label:
                font_size: 20
                text: '00'
                canvas.before:
                    Color:
                        rgba: .5, .5, .5, 1
                    Line:
                        width: 2
                        rectangle: self.x, self.y, self.width, self.height
        BoxLayout:
            size_hint_y: 0.2
            canvas.before:
                Color:
                    rgba: .5, .5, .5, 1
                Line:
                    width: 2
                    rectangle: self.x, self.y, self.width, self.height
            Button:
                text: "Pauze"
                on_press: timer.pause()
            Button:
                text: "Hervatten"
                on_press: timer.resume()
            Button:
                text: "Stoppen"
                #on_press: timer.reset()
        Label:
            text: ''
    ################################### Widget template ##########################################
    
    <Main@Widget>:
        rows: 2 # 2 rijen
        cols: 4 # 4 colums
        padding: 10 
        spacing: 10
        ################################### Tafel 1 ##########################################
        BoxLayout:
            canvas.before:
                Color:
                    rgba: .5, .5, .5, 1
                Line:
                    width: 2
                    rectangle: self.x, self.y, self.width, self.height
            orientation: 'vertical'
            Label:
                size_hint_y: 0.15
                font_size: 25
                canvas.before:
                    Color:
                        rgba: .5, .5, .5, 1
                    Rectangle:
                        pos: self.pos
                        size: self.size
                text: 'Tafel 1'
            CrudeTimerGrid:
                id: tafel1
        ################################### Tafel 1 ##########################################
    
        ################################### Tafel 2 ##########################################
        BoxLayout:
            canvas.before:
                Color:
                    rgba: .5, .5, .5, 1
                Line:
                    width: 2
                    rectangle: self.x, self.y, self.width, self.height
            orientation: 'vertical'
            Label:
                size_hint_y: 0.15
                font_size: 25
                canvas.before:
                    Color:
                        rgba: .5, .5, .5, 1
                    Rectangle:
                        pos: self.pos
                        size: self.size
                text: 'Tafel 2'
            CrudeTimerGrid:
                id: tafel2
        ################################### Tafel 2 ##########################################
    
        ################################### Tafel 3 ##########################################
        BoxLayout:
            canvas.before:
                Color:
                    rgba: .5, .5, .5, 1
                Line:
                    width: 2
                    rectangle: self.x, self.y, self.width, self.height
            orientation: 'vertical'
            Label:
                size_hint_y: 0.15
                font_size: 25
                canvas.before:
                    Color:
                        rgba: .5, .5, .5, 1
                    Rectangle:
                        pos: self.pos
                        size: self.size
                text: 'Tafel 3'
            CrudeTimerGrid:
                id: tafel3
        ################################### Tafel 3 ##########################################
    
        ################################### Tafel 4 ##########################################
        BoxLayout:
            canvas.before:
                Color:
                    rgba: .5, .5, .5, 1
                Line:
                    width: 2
                    rectangle: self.x, self.y, self.width, self.height
            orientation: 'vertical'
            Label:
                size_hint_y: 0.15
                font_size: 25
                canvas.before:
                    Color:
                        rgba: .5, .5, .5, 1
                    Rectangle:
                        pos: self.pos
                        size: self.size
                text: 'Tafel 4'
            CrudeTimerGrid:
                id: tafel4
        ################################### Tafel 4 ##########################################
    
        ################################### Tafel 5 ##########################################
        BoxLayout:
            canvas.before:
                Color:
                    rgba: .5, .5, .5, 1
                Line:
                    width: 2
                    rectangle: self.x, self.y, self.width, self.height
            orientation: 'vertical'
            Label:
                size_hint_y: 0.15
                font_size: 25
                canvas.before:
                    Color:
                        rgba: .5, .5, .5, 1
                    Rectangle:
                        pos: self.pos
                        size: self.size
                text: 'Tafel 5'
            CrudeTimerGrid:
                id: tafel5
        ################################### Tafel 5 ##########################################
    
        ################################### Tafel 6 ##########################################
        BoxLayout:
            canvas.before:
                Color:
                    rgba: .5, .5, .5, 1
                Line:
                    width: 2
                    rectangle: self.x, self.y, self.width, self.height
            orientation: 'vertical'
            Label:
                size_hint_y: 0.15
                font_size: 25
                canvas.before:
                    Color:
                        rgba: .5, .5, .5, 1
                    Rectangle:
                        pos: self.pos
                        size: self.size
                text: 'Tafel 6'
            CrudeTimerGrid:
                id: tafel6
        ################################### Tafel 6 ##########################################
    
        ################################### Tafel 7 ##########################################
        BoxLayout:
            canvas.before:
                Color:
                    rgba: .5, .5, .5, 1
                Line:
                    width: 2
                    rectangle: self.x, self.y, self.width, self.height
            orientation: 'vertical'
            Label:
                size_hint_y: 0.15
                font_size: 25
                canvas.before:
                    Color:
                        rgba: .5, .5, .5, 1
                    Rectangle:
                        pos: self.pos
                        size: self.size
                text: 'Tafel 7'
            CrudeTimerGrid:
                id: tafel7
        ################################### Tafel 7 ##########################################
    
        ################################### Tafel 8 ##########################################
        BoxLayout:
            canvas.before:
                Color:
                    rgba: .5, .5, .5, 1
                Line:
                    width: 2
                    rectangle: self.x, self.y, self.width, self.height
            orientation: 'vertical'
            Label:
                size_hint_y: 0.15
                font_size: 25
                canvas.before:
                    Color:
                        rgba: .5, .5, .5, 1
                    Rectangle:
                        pos: self.pos
                        size: self.size
                text: 'Tafel 8'
            CrudeTimerGrid:
                id: tafel8
        ################################### Tafel 8 ##########################################
    
    Main:
    
    所有魔法发生的类是类
    CrudeTimerGrid()
    。 我怎样才能使我的计时器不会在每次点击简历按钮时重置

    编辑:设法解决了我的问题! 我制作了一个事件(
    self.event=Clock.schedule\u interval(self.tick,1)
    ),有两个按钮可以暂停和恢复。
    我使用暂停按钮(
    Clock.unschedule(self.event)
    )来取消对事件的计划,使用恢复按钮(
    Clock.schedule\u once(self.event)
    )来重新安排我的计时器。

    使用
    Clock.unschedule(self.tick)
    将无法取消对Kivy Clock事件的计划。请参考下面的例子

    日程 替换

    Clock.schedule_interval(self.tick, 1)
    

    计划外 这样您就可以使用 或者


    您将无法使用
    Clock.unschedule(self.tick)
    取消Kivy时钟事件的计划。请参考下面的例子

    日程 替换

    Clock.schedule_interval(self.tick, 1)
    

    计划外 这样您就可以使用 或者


    我尝试了你的建议,时间的重置是固定的,但我仍然有一个问题,当我点击我的恢复按钮两次时,两个计时器同时运行,这两个计时器都改变了标签,你会看到两个计时器之间的时间变化,因为你有8个表/窗口,您应该有8个启动事件,即
    self.tafel?=时钟.计划时间间隔(self.tick,1)
    ,以及8个取消/计划外事件,即
    时钟.计划外事件(self.tafel?
    何处?=1到8.你是否按照你的建议解决了我的问题,唯一不同的是安排一次时间来再次启动我的活动。谢谢你的建议,这很有帮助!我尝试了你的建议,时间的重置是固定的,但我仍然有一个问题,当我点击我的恢复按钮两次时,两个计时器同时运行,这两个计时器都改变了标签,你会看到两个计时器之间的时间变化,因为你有8个表/窗口,您应该有8个启动事件,即
    self.tafel?=时钟.计划时间间隔(self.tick,1)
    ,以及8个取消/计划外事件,即
    时钟.计划外事件(self.tafel?
    何处?=1到8.你是否按照你的建议解决了我的问题,唯一不同的是安排一次时间来再次启动我的活动。谢谢你的建议,这很有帮助!
    self.event = Clock.schedule_interval(self.tick, 1)
    
    self.event.cancel()
    
    Clock.unschedule(self.event)