首页 > 解决方案 > 同时运行kivy和无限循环

问题描述

我需要倒计时,然后在手机上使用。我听说 kivy 是手机的好图形,所以我尝试使用它。我试图同时运行无限的while循环来倒计时和创建窗口并显示剩余时间的kivy应用程序。我也在使用 pygame 时钟来计时。但是当我运行这段代码时,while循环正在计算时间,但它只会创建白色的空白窗口,一段时间后会创建另一个窗口。我究竟做错了什么 ?

from kivy.app import App
from kivy.uix.widget import Widget
from kivy.properties import ObjectProperty
from kivy.uix.floatlayout import FloatLayout
from kivy.lang import Builder
from kivy.uix.image import Image
from kivy.core.window import Window
from multiprocessing import Process
import pygame


class MyFloat(FloatLayout):
    def __init__(self, **kwargs):
        super(MyFloat, self).__init__(**kwargs)

        self.background = Image(source="textures/background.jpg", allow_stretch=True, keep_ratio=False)
        self.add_widget(self.background)


class MyApp(App):
    def build(self):
        return MyFloat()


def check_time():
    global days
    global hours
    global minutes
    global seconds
    global miliSeconds

    miliSeconds -= 1
    if miliSeconds < 0:
        miliSeconds += 100
        seconds -= 1
    if seconds < 0:
        seconds += 60
        minutes -= 1
    if minutes < 0:
        minutes += 60
        hours -= 1
    if hours < 0:
        hours += 24
        days -= 1
    if days < 0:
        global active
        active = False
        print("End")

    print("days: ", days)
    print("hours: ", hours)
    print("minutes: ", minutes)
    print("seconds: ", seconds)
    print("miliseconds: ", miliSeconds)


def loop():
    while active:
        check_time()

        clock.tick(100)


clock = pygame.time.Clock()

days = 0
hours = 0
minutes = 0
seconds = 30
miliSeconds = 0
active = True


if __name__ == "__main__":
    p1 = Process(target=loop)
    p2 = Process(target=MyApp().run)

    p1.start()
    p2.start()

标签: pythonkivy

解决方案


你不需要也不需要pygame因为while Truekivy时钟功能

# call my_callback every 0.5 seconds
Clock.schedule_interval(my_callback, 0.5)

# call my_callback in 5 seconds
Clock.schedule_once(my_callback, 5)

# call my_callback as soon as possible (usually next frame.)
Clock.schedule_once(my_callback)

开始任务:

task = Clock.schedule_interval(check_time, 0.1)

停止任务:

task.cancel()

并且您的函数将delta_time在两次执行之间执行,因此您可以检查它是否恰好在之后执行0.1 second。您可以使用它来显示正确的时间。


from kivy.app import App
from kivy.uix.widget import Widget
from kivy.properties import ObjectProperty
from kivy.uix.floatlayout import FloatLayout
from kivy.lang import Builder
from kivy.uix.image import Image
from kivy.core.window import Window

from kivy.clock import Clock

class MyFloat(FloatLayout):
    def __init__(self, **kwargs):
        super().__init__(**kwargs)

        self.background = Image(source="textures/background.jpg", allow_stretch=True, keep_ratio=False)
        self.add_widget(self.background)

class MyApp(App):
    def build(self):
        return MyFloat()


def check_time(dt):
    global days
    global hours
    global minutes
    global seconds
    global miliSeconds
    global active

    miliSeconds -= 1
    if miliSeconds < 0:
        miliSeconds += 100
        seconds -= 1
    if seconds < 0:
        seconds += 60
        minutes -= 1
    if minutes < 0:
        minutes += 60
        hours -= 1
    if hours < 0:
        hours += 24
        days -= 1
    if days < 0:
        active = False
        print("End")
        task.cancel()  # <-- stoping task

    print("days: ", days)
    print("hours: ", hours)
    print("minutes: ", minutes)
    print("seconds: ", seconds)
    print("miliseconds: ", miliSeconds)

    
days = 0
hours = 0
minutes = 0
seconds = 1
miliSeconds = 0
active = True


if __name__ == "__main__":
    task = Clock.schedule_interval(check_time, 0.1)  #  <-- starting task
    MyApp().run()

编辑:

Clock用于显示当前时间的示例Label

from kivy.app import App
from kivy.core.window import Window
from kivy.uix.floatlayout import FloatLayout
from kivy.uix.label import Label
from kivy.clock import Clock
import datetime

class MyFloat(FloatLayout):
    def __init__(self, **kwargs):
        super().__init__(**kwargs)

        self.label = Label()
        self.add_widget(self.label)
        self.task = Clock.schedule_interval(self.update_label, 0.1)  

    def update_label(self, dt):
        now = datetime.datetime.now()
        self.label.text = now.strftime("%Y.%m.%d  %H:%M.%S")
        
class MyApp(App):
    def build(self):
        return MyFloat()

if __name__ == "__main__":
    MyApp().run()

顺便提一句:

当您必须运行长时间运行的代码时,您可能需要multiprocessing/ 。threading但它可能还需要Queue与主进程通信。通常 GUI 不能修改分离的进程/线程中的小部件。


推荐阅读