Пытаюсь сделать аналоговые часы - PullRequest
0 голосов
/ 06 ноября 2019

Я пытаюсь выучить Киви, и я подумал, что это будет хороший проект. Я пытаюсь сделать аналоговые часы, используя библиотеку Kivy в Python. но я не могу понять, как заставить его обновляться каждую секунду.

Я попробовал пару вещей, которые я узнал из уроков. но я думаю, что я делаю это неправильно. Я не очень знаком с объектно-ориентированным программированием, и я думаю, именно поэтому он не работает.

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

, когда я запускаю его, ничего не происходит. окно всплывает, но я не вижу белой линии. я уверен, что где-то допустил ошибку новичка.

Ответы [ 2 ]

0 голосов
/ 07 ноября 2019

По крайней мере, у вас есть следующие ошибки:

  • Для рисования вы должны использовать холст виджета.
  • Если вы хотите, чтобы он был погашен, вы должны обновить инструкции.
  • Не злоупотребляйте глобальными переменными, в этом случае лучше использовать свойства 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()

enter image description here

0 голосов
/ 07 ноября 2019
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

Вы создаете объект Color и объект Line, но не делаете ничего, что заставило бы их быть нарисованными на экране. ,Вместо этого используйте что-то вроде:

with self.canvas:
    Color(...)
    Line(...)

Этот синтаксис заставляет Color и Line автоматически добавляться на холст указанного виджета.

 Clock.schedule_interval(ScatterWidget.simple_analog, 1)

Это не делает то, что вы хотите, выВы вызываете метод simple_analog через сам класс, а не через какой-либо конкретный экземпляр. Это не вызывает проблем сейчас, потому что код не использует состояние класса, но он сломается, как только вы попробуете что-то нетривиальное.

Вместо этого создайте экземпляр классаи запланируйте метод этого экземпляра:

def build(self):
    your_instance = SatterWidget()
    Clock.schedule_interval(your_instance.simple_analog, 1)
    return your_instance
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...