Python 3.x 试着做一个模拟时钟

Python 3.x 试着做一个模拟时钟,python-3.x,kivy,Python 3.x,Kivy,我正在努力学习Kivy,我认为这将是一个很好的项目。 我试图用python中的Kivy库制作一个模拟时钟。 但我不知道如何让它每秒钟更新一次 我尝试了从教程中学到的一些东西。但我认为我做错了。我对面向对象编程不太熟悉,我想这就是它不起作用的原因 from kivy.app import App from kivy.uix.scatter import Scatter from kivy.uix.label import Label from kivy.uix.floatlayout import

我正在努力学习Kivy,我认为这将是一个很好的项目。 我试图用python中的Kivy库制作一个模拟时钟。 但我不知道如何让它每秒钟更新一次

我尝试了从教程中学到的一些东西。但我认为我做错了。我对面向对象编程不太熟悉,我想这就是它不起作用的原因

from kivy.app import App
from kivy.uix.scatter import Scatter
from kivy.uix.label import Label
from kivy.uix.floatlayout import FloatLayout
from kivy.uix.textinput import TextInput
from kivy.uix.boxlayout import BoxLayout
from kivy.properties import ListProperty, ObjectProperty
from kivy.graphics.vertex_instructions import (Rectangle, Ellipse, Line)
from kivy.graphics.context_instructions import Color
from kivy.core.window import Window
from kivy.clock import Clock
import random
import math


leline = [513.0, 1013.0, 565.2642316338267, 1010.2609476841367, 616.9558454088797, 1002.0738003669028,
          667.5084971874737, 988.5282581475767, 716.3683215379001, 969.7727288213005, 763.0, 946.0127018922193,
          806.8926261462366, 917.5084971874737, 847.5653031794291, "insert the rest of the 60 cordinates that form a perfect cercle here"]

linethick = 13

class ScatterWidget(BoxLayout):
    global x
    global y
    x = 0
    y = 1

    def simple_analog(self, *args):
        global x
        global y
        Color(1, 1, 1, 1)
        Line(points=[(Window.width / 2), (Window.height / 2),
                     leline[x], leline[y],
                     ],
             width=linethick)
        x += 2
        y += 2
        if x > 60:
            x = 0
        if y > 60:
            y = 0


class CoolClockApp(App):
    def build(self):
        Clock.schedule_interval(ScatterWidget.simple_analog, 1)
        return ScatterWidget()


if __name__ == "__main__":
    CoolClockApp().run()
当我运行它时,什么也没发生。窗口弹出,但我看不到画白线。我肯定我在什么地方犯了个新手错误

class ScatterWidget(BoxLayout):
    global x
    global y
    x = 0
    y = 1
即使你想使用全局变量,你不应该使用全局变量,但这不是一种方法。但是,这至少不是你眼前问题的原因

def simple_analog(self, *args):
    global x
    global y
    Color(1, 1, 1, 1)
    Line(points=[(Window.width / 2), (Window.height / 2),
                 leline[x], leline[y],
                 ],
         width=linethick)
    x += 2
    y += 2
    if x > 60:
        x = 0
    if y > 60:
        y = 0
创建一个颜色对象和一个线条对象,但不要做任何会导致它们在屏幕上绘制的事情。相反,请使用以下内容:

with self.canvas:
    Color(...)
    Line(...)
此语法导致颜色和线条自动添加到指定小部件的画布中

 Clock.schedule_interval(ScatterWidget.simple_analog, 1)
这并不是你想要的,你是通过类本身调用simple_模拟方法,而不是通过任何特定的实例。它现在没有引起问题,因为代码没有使用任何类状态,但只要您尝试一些非平凡的东西,它就会崩溃

相反,创建类的实例并计划该实例的方法:

def build(self):
    your_instance = SatterWidget()
    Clock.schedule_interval(your_instance.simple_analog, 1)
    return your_instance

至少您有以下错误:

  • 对于绘制,必须使用小部件的画布
  • 如果您希望偿还,则必须更新说明
  • 不要滥用全局变量,在这种情况下,最好使用Kivy属性
考虑到上述情况,解决方案是:

import datetime
import math

from kivy.app import App
from kivy.clock import Clock
from kivy.graphics.context_instructions import Color
from kivy.graphics.vertex_instructions import Ellipse, Line
from kivy.properties import NumericProperty
from kivy.uix.widget import Widget


class ClockWidget(Widget):
    radius = NumericProperty(250)

    seconds_length = NumericProperty(200)
    minutes_length = NumericProperty(150)
    hours_length = NumericProperty(100)

    seconds_linethick = NumericProperty(5)
    minutes_linethick = NumericProperty(8)
    hours_linethick = NumericProperty(12)

    def __init__(self, **kwargs):
        super().__init__(**kwargs)

        self.bind(
            size=self.recalculate_line,
            seconds_length=self.recalculate_line,
            minutes_length=self.recalculate_line,
            hours_length=self.recalculate_line,
        )

        Clock.schedule_interval(self.recalculate_line, 1)

        with self.canvas:
            Color(1, 1, 0, 1)
            self.circle = Ellipse()
            Color(1, 1, 1, 1)
            self.seconds_line = Line()
            Color(0, 0, 1, 1)
            self.minutes_line = Line()
            Color(1, 0, 0, 1)
            self.hours_line = Line()

    def recalculate_line(self, *args):
        now = datetime.datetime.now()
        angle_seconds = math.pi / 2 - (now.second * 2 * math.pi / 60.0)
        angle_minutes = math.pi / 2 - (
            (now.minute + now.second / 60.0) * 2 * math.pi / 60.0
        )
        angle_hours = (
            math.pi / 2
            - (now.hour + now.minute / 60.0 + now.second / 3600.0) * 2 * math.pi / 12
        )

        self.circle.size = 2 * self.radius, 2 * self.radius
        self.circle.pos = (self.center[0] - self.radius, self.center[1] - self.radius)

        for angle, line, length, linethick in zip(
            (angle_seconds, angle_minutes, angle_hours),
            (self.seconds_line, self.minutes_line, self.hours_line),
            (self.seconds_length, self.minutes_length, self.hours_length),
            (self.seconds_linethick, self.minutes_linethick, self.hours_linethick),
        ):

            x = length * math.cos(angle)
            y = length * math.sin(angle)
            line.width = linethick

            points = [
                self.width / 2,
                self.height / 2,
                self.width / 2 + x,
                self.height / 2 + y,
            ]
            line.points = points


class CoolClockApp(App):
    def build(self):
        return ClockWidget()


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