一步一步教你用Python?pyglet仿制鴻蒙系統(tǒng)里的時鐘

鴻蒙時鐘
本篇將用python pyglet庫復(fù)刻華為手機鴻蒙系統(tǒng)鬧鐘程序的時鐘,先在上圖中抓取出時分秒針及刻度、表盤的顏色RGB值:
bHour = (42, 43, 48, 255)
bMinute = (70, 71, 75, 255)
rSecond = (240, 70, 20, 255)
gScale = 215, 220, 230
wBackground = 248, 250, 252
1. 繪制圓盤
首先要畫一圓Circle,并用直線Line等分成60份。
self.circle = pyglet.shapes.Circle(x, y, R, color=wBackground, batch=batch)
self.scales = [pyglet.shapes.Line(x, y, x+R*cos(i*Pi/30), y+R*sin(i*Pi/30),
width=2, color=gScales, batch=batch) for i in range(60)]直線除圓心外的另一端點的坐標計算公式,如下圖所示:

代碼:
import pyglet
from math import pi, sin, cos
window = pyglet.window.Window(800, 500, caption='圓盤')
pyglet.gl.glClearColor(1, 1, 1, 1)
batch = pyglet.graphics.Batch()
R = 200
wBackground = 248, 250, 252
gScales = 215, 220, 230
class Watch:
def __init__(self, x, y):
self.circle = pyglet.shapes.Circle(x, y, R, color=wBackground, batch=batch)
self.scales = [pyglet.shapes.Line(x, y, x+R*cos(i*pi/30), y+R*sin(i*pi/30),
width=2, color=gScales, batch=batch) for i in range(60)]
@window.event
def on_draw():
window.clear()
batch.draw()
watch = Watch(window.width/2, window.height/2)
pyglet.app.run()2. 創(chuàng)建表類
改造這個Watch類,可設(shè)置圓心和半徑,并讓它成為pyglet.window.Window的子類。

import pyglet
from math import sin, cos, pi
wBackground = (248, 250, 252, 255)
gScales = (215, 220, 230, 255)
class Watch(pyglet.window.Window):
def __init__(self, x, y, R=200, width=800, height=500, caption='圓盤'):
super().__init__(width, height, caption=caption)
pyglet.gl.glClearColor(1, 1, 1, 1)
self.batch = pyglet.graphics.Batch()
self.circle = pyglet.shapes.Circle(x, y, R,
color=wBackground, batch=self.batch)
self.scales = [pyglet.shapes.Line(x, y, x+R*cos(i*pi/30), y+R*sin(i*pi/30),
width=2, color=gScales, batch=self.batch) for i in range(60)]
def on_draw(self):
self.clear()
self.batch.draw()
def run(self):
pyglet.app.run()
watch = Watch(500, 300, 150)
watch.run()3. 繪制刻度
擴大圓面并縮短和加粗直線,表盤和刻度的大致輪廓就出現(xiàn)了。

代碼:
import pyglet
from math import sin, cos, pi
wBackground = (248, 250, 252, 255)
gScales = (215, 220, 230, 255)
class Watch(pyglet.window.Window):
def __init__(self, x, y, R=200, width=800, height=500, caption='刻度'):
super().__init__(width, height, caption=caption)
pyglet.gl.glClearColor(1, 1, 1, 1)
self.batch = pyglet.graphics.Batch()
self.circle = pyglet.shapes.Circle(x, y, R*1.05,
color=wBackground, batch=self.batch)
self.scales = [pyglet.shapes.Line(x+R*cos(i*pi/30), y+R*sin(i*pi/30),
x+R*0.95*cos(i*pi/30), y+0.95*R*sin(i*pi/30),
width=3, color=gScales, batch=self.batch) for i in range(60)]
for i, scale in enumerate(self.scales):
if i%5==0:
scale.width, scale.x2, scale.y2 = 5, x+R*0.92*cos(i*pi/30), y+0.92*R*sin(i*pi/30)
def on_draw(self):
self.clear()
self.batch.draw()
def run(self):
pyglet.app.run()
watch = Watch(400, 250)
watch.run()4. 刻度數(shù)值
在整點的刻度值邊上用標簽標注上1~12的數(shù)字。
self.labels = [pyglet.text.Label(str((2-i)%12+1), font_size=24, color=(0,0,0,255),
x=x+R*0.82*cos(i*pi/6), y=y+0.82*R*sin(i*pi/6)+5, anchor_x='center',
anchor_y='center', batch=self.batch) for i in range(12)]
代碼:
import pyglet
from math import sin, cos, pi
wBackground = (248, 250, 252, 255)
gScales = (215, 220, 230, 255)
rSecond = (240, 70, 20, 255)
class Watch(pyglet.window.Window):
def __init__(self, x, y, R=200, width=800, height=500, caption='指針'):
super().__init__(width, height, caption=caption)
pyglet.gl.glClearColor(1, 1, 1, 1)
self.batch = pyglet.graphics.Batch()
self.circle = pyglet.shapes.Circle(x, y, R*1.05, color=wBackground, batch=self.batch)
self.scales = [pyglet.shapes.Line(x+R*cos(i*pi/30), y+R*sin(i*pi/30),
x+R*0.95*cos(i*pi/30), y+0.95*R*sin(i*pi/30),
width=3, color=gScales, batch=self.batch) for i in range(60)]
for i,scale in enumerate(self.scales):
if i%5==0:
scale.width, scale.x2, scale.y2 = 5, x+R*0.92*cos(i*pi/30), y+0.92*R*sin(i*pi/30)
self.labels = [pyglet.text.Label(str((2-i)%12+1), font_size=R*0.12, color=(0,0,0,255),
x=x+R*0.82*cos(i*pi/6), y=y+0.82*R*sin(i*pi/6)-R*0.06, anchor_x='center',
batch=self.batch) for i in range(12)]
def on_draw(self):
self.clear()
self.batch.draw()
def run(self):
pyglet.app.run()
watch = Watch(400, 250)
watch.run()5. 添加指針
時、分、秒針,用三個圓三條直線來表示。
self.circle1 = pyglet.shapes.Circle(x, y, R*0.08, color=bHour)
self.hour = pyglet.shapes.Line(x, y, x+R*0.7, y, width=9, color=bHour)
self.minute = pyglet.shapes.Line(x, y, x+R*0.9, y, width=7, color=bMinute)
self.second = pyglet.shapes.Line(x, y, x+R*1.1, y, width=5, color=rSecond)
self.circle2 = pyglet.shapes.Circle(x, y, R*0.05, color=rSecond)
self.circle3 = pyglet.shapes.Circle(x, y, R*0.02, color=wWhite)不用擔心秒針長過表盤圓面,轉(zhuǎn)動前會作“移動”處理。

代碼:
import pyglet
from math import sin, cos, pi
wBackground = (248, 250, 252, 255)
gScales = (215, 220, 230, 255)
rSecond = (240, 70, 20, 255)
bMinute = (70, 71, 75, 255)
bHour = (42, 43, 48, 255)
wWhite = (255, 255, 255, 255)
class Watch(pyglet.window.Window):
def __init__(self, x, y, R=200, width=800, height=500, caption='指針'):
super().__init__(width, height, caption=caption)
pyglet.gl.glClearColor(1, 1, 1, 1)
self.batch = pyglet.graphics.Batch()
self.circle = pyglet.shapes.Circle(x, y, R*1.05, color=wBackground, batch=self.batch)
self.scales = [pyglet.shapes.Line(x+R*cos(i*pi/30), y+R*sin(i*pi/30),
x+R*0.95*cos(i*pi/30), y+0.95*R*sin(i*pi/30),
width=3, color=gScales, batch=self.batch) for i in range(60)]
for i,scale in enumerate(self.scales):
if i%5==0:
scale.width, scale.x2, scale.y2 = 5, x+R*0.92*cos(i*pi/30), y+0.92*R*sin(i*pi/30)
self.labels = [pyglet.text.Label(str((2-i)%12+1), font_size=R*0.12, color=(0,0,0,255),
x=x+R*0.82*cos(i*pi/6), y=y+0.82*R*sin(i*pi/6)-R*0.06, anchor_x='center',
batch=self.batch) for i in range(12)]
self.circle1 = pyglet.shapes.Circle(x, y, R*0.08, color=bHour, batch=self.batch)
self.hour = pyglet.shapes.Line(x, y, x+R*0.7, y, width=9, color=bHour, batch=self.batch)
self.minute = pyglet.shapes.Line(x, y, x+R*0.9, y, width=7, color=bMinute, batch=self.batch)
self.second = pyglet.shapes.Line(x, y, x+R*1.1, y, width=5, color=rSecond, batch=self.batch)
self.circle2 = pyglet.shapes.Circle(x, y, R*0.05, color=rSecond, batch=self.batch)
self.circle3 = pyglet.shapes.Circle(x, y, R*0.02, color=wWhite, batch=self.batch)
def on_draw(self):
self.clear()
self.batch.draw()
def run(self):
pyglet.app.run()
watch = Watch(400, 250)
watch.run()
6. 轉(zhuǎn)動指針
時、分、秒針的轉(zhuǎn)動運用Line控件的旋轉(zhuǎn)屬性.rotation,這種方法要比修改端點坐標要方便。
默認的旋轉(zhuǎn)中心是直線的左端點,屬性.anchor_position可以修改中心坐標。
self.second.anchor_position = (R*0.1, 0)
self.second.rotation = 210
self.minute.rotation = 24
self.hour.rotation = 160
代碼:
import pyglet
from math import sin, cos, pi
wBackground = (248, 250, 252, 255)
gScales = (215, 220, 230, 255)
rSecond = (240, 70, 20, 255)
bMinute = (70, 71, 75, 255)
bHour = (42, 43, 48, 255)
wWhite = (255, 255, 255, 255)
class Watch(pyglet.window.Window):
def __init__(self, x, y, R=200, width=800, height=500, caption='指針'):
super().__init__(width, height, caption=caption)
pyglet.gl.glClearColor(1, 1, 1, 1)
self.batch = pyglet.graphics.Batch()
self.circle = pyglet.shapes.Circle(x, y, R*1.05, color=wBackground, batch=self.batch)
self.scales = [pyglet.shapes.Line(x+R*cos(i*pi/30), y+R*sin(i*pi/30),
x+R*0.95*cos(i*pi/30), y+0.95*R*sin(i*pi/30),
width=3, color=gScales, batch=self.batch) for i in range(60)]
for i,scale in enumerate(self.scales):
if i%5==0:
scale.width, scale.x2, scale.y2 = 5, x+R*0.92*cos(i*pi/30), y+0.92*R*sin(i*pi/30)
self.labels = [pyglet.text.Label(str((2-i)%12+1), font_size=R*0.12, color=(0,0,0,255),
x=x+R*0.82*cos(i*pi/6), y=y+0.82*R*sin(i*pi/6)-R*0.06, anchor_x='center',
batch=self.batch) for i in range(12)]
self.circle1 = pyglet.shapes.Circle(x, y, R*0.08, color=bHour, batch=self.batch)
self.hour = pyglet.shapes.Line(x, y, x+R*0.7, y, width=9, color=bHour, batch=self.batch)
self.minute = pyglet.shapes.Line(x, y, x+R*0.9, y, width=7, color=bMinute, batch=self.batch)
self.second = pyglet.shapes.Line(x, y, x+R*1.1, y, width=5, color=rSecond, batch=self.batch)
self.circle2 = pyglet.shapes.Circle(x, y, R*0.05, color=rSecond, batch=self.batch)
self.circle3 = pyglet.shapes.Circle(x, y, R*0.02, color=wWhite, batch=self.batch)
self.second.anchor_position = (R*0.1, 0)
self.second.rotation = 210
self.minute.rotation = 24
self.hour.rotation = 160
def on_draw(self):
self.clear()
self.batch.draw()
def run(self):
pyglet.app.run()
watch = Watch(400, 250)
watch.run()7. 聯(lián)動時間
聯(lián)動系統(tǒng)時鐘,使用datetime.now()獲取當前時間的時、分、秒的值。
now = datetime.now()
h, m, s = now.hour, now.minute, now.second
self.second.rotation = -90 + s*6
self.minute.rotation = -90 + m*6 + s/10
self.hour.rotation = -90 + h%12*30 + m/2
代碼:
import pyglet
from math import sin, cos, pi
from datetime import datetime
wBackground = (248, 250, 252, 255)
gScales = (215, 220, 230, 255)
rSecond = (240, 70, 20, 255)
bMinute = (70, 71, 75, 255)
bHour = (42, 43, 48, 255)
wWhite = (255, 255, 255, 255)
class Watch(pyglet.window.Window):
def __init__(self, x, y, R=200, width=800, height=500, caption='指針'):
super().__init__(width, height, caption=caption)
pyglet.gl.glClearColor(1, 1, 1, 1)
self.batch = pyglet.graphics.Batch()
self.circle = pyglet.shapes.Circle(x, y, R*1.05, color=wBackground, batch=self.batch)
self.scales = [pyglet.shapes.Line(x+R*cos(i*pi/30), y+R*sin(i*pi/30),
x+R*0.95*cos(i*pi/30), y+0.95*R*sin(i*pi/30),
width=3, color=gScales, batch=self.batch) for i in range(60)]
for i,scale in enumerate(self.scales):
if i%5==0:
scale.width, scale.x2, scale.y2 = 5, x+R*0.92*cos(i*pi/30), y+0.92*R*sin(i*pi/30)
self.labels = [pyglet.text.Label(str((2-i)%12+1), font_size=R*0.12, color=(0,0,0,255),
x=x+R*0.82*cos(i*pi/6), y=y+0.82*R*sin(i*pi/6)-R*0.06, anchor_x='center',
batch=self.batch) for i in range(12)]
self.circle1 = pyglet.shapes.Circle(x, y, R*0.08, color=bHour, batch=self.batch)
self.hour = pyglet.shapes.Line(x, y, x+R*0.7, y, width=9, color=bHour, batch=self.batch)
self.minute = pyglet.shapes.Line(x, y, x+R*0.9, y, width=7, color=bMinute, batch=self.batch)
self.second = pyglet.shapes.Line(x, y, x+R*1.1, y, width=5, color=rSecond, batch=self.batch)
self.circle2 = pyglet.shapes.Circle(x, y, R*0.05, color=rSecond, batch=self.batch)
self.circle3 = pyglet.shapes.Circle(x, y, R*0.02, color=wWhite, batch=self.batch)
self.second.anchor_position = (R*0.1, 0)
self.update()
def update(self):
now = datetime.now()
h, m, s = now.hour, now.minute, now.second
self.second.rotation = -90 + s*6
self.minute.rotation = -90 + m*6 + s/10
self.hour.rotation = -90 + h%12*30 + m/2
def on_draw(self):
self.clear()
self.batch.draw()
def run(self):
pyglet.app.run()
watch = Watch(400, 250)
watch.run()8. 運行時鐘
使用pyglet.clock.schedule_interval(self.update, 0.2)每秒更新5次。
總得來說,本次復(fù)刻比較完美,但直線控件在非水平或垂直狀態(tài),特別是小夾角時鋸齒很嚴重。

完整代碼:
import pyglet
from math import sin, cos, pi
from datetime import datetime
class Watch(pyglet.window.Window):
def __init__(self, x, y, R=200, width=800, height=500, caption='時鐘'):
super().__init__(width, height, caption=caption)
wBackground = (248, 250, 252, 255)
gScales = (215, 220, 230, 255)
rSecond = (240, 70, 20, 255)
bMinute = (70, 71, 75, 255)
bHour = (42, 43, 48, 255)
wWhite = (255, 255, 255, 255)
pyglet.gl.glClearColor(1, 1, 1, 1)
self.batch = pyglet.graphics.Batch()
self.circle = pyglet.shapes.Circle(x, y, R*1.05, color=wBackground, batch=self.batch)
self.scales = [pyglet.shapes.Line(x+R*cos(i*pi/30), y+R*sin(i*pi/30),
x+R*0.95*cos(i*pi/30), y+0.95*R*sin(i*pi/30),
width=3, color=gScales, batch=self.batch) for i in range(60)]
for i,scale in enumerate(self.scales):
if i%5==0:
scale.width, scale.x2, scale.y2 = 5, x+R*0.92*cos(i*pi/30), y+0.92*R*sin(i*pi/30)
self.labels = [pyglet.text.Label(str((2-i)%12+1), font_size=R*0.12, color=(0,0,0,255),
x=x+R*0.82*cos(i*pi/6), y=y+0.82*R*sin(i*pi/6)-R*0.06, anchor_x='center',
batch=self.batch) for i in range(12)]
self.circle1 = pyglet.shapes.Circle(x, y, R*0.08, color=bHour, batch=self.batch)
self.hour = pyglet.shapes.Line(x, y, x+R*0.7, y, width=9, color=bHour, batch=self.batch)
self.minute = pyglet.shapes.Line(x, y, x+R*0.9, y, width=7, color=bMinute, batch=self.batch)
self.second = pyglet.shapes.Line(x, y, x+R*1.1, y, width=5, color=rSecond, batch=self.batch)
self.circle2 = pyglet.shapes.Circle(x, y, R*0.05, color=rSecond, batch=self.batch)
self.circle3 = pyglet.shapes.Circle(x, y, R*0.02, color=wWhite, batch=self.batch)
self.second.anchor_position = (R*0.1, 0)
self.update(self.event)
pyglet.clock.schedule_interval(self.update, 0.2)
def update(self, event):
now = datetime.now()
h, m, s = now.hour, now.minute, now.second
self.second.rotation = -90 + s*6
self.minute.rotation = -90 + m*6 + s/10
self.hour.rotation = -90 + h%12*30 + m/2
def on_draw(self):
self.clear()
self.batch.draw()
def run(self):
pyglet.app.run()
watch = Watch(400, 250)
watch.run()完
總結(jié)
到此這篇關(guān)于一步一步教你用Python pyglet仿制鴻蒙系統(tǒng)里的時鐘的文章就介紹到這了,更多相關(guān)Python pyglet仿鴻蒙的時鐘內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
同時安裝Python2 & Python3 cmd下版本自由選擇的方法
下面小編就為大家分享一篇同時安裝Python2 & Python3 cmd下版本自由選擇的方法,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2017-12-12
Pytorch如何打印與Keras的model.summary()類似的輸出(最新推薦)
這篇文章主要介紹了Pytorch如何打印與Keras的model.summary()類似的輸出,本文給大家介紹的非常詳細,對大家的學(xué)習或工作具有一定的參考借鑒價值,需要的朋友可以參考下2023-07-07
Python ORM框架SQLAlchemy學(xué)習筆記之關(guān)系映射實例
這篇文章主要介紹了Python ORM框架SQLAlchemy學(xué)習筆記之關(guān)系映射實例,Classic (經(jīng)典模式)和Modern (現(xiàn)代模式),分別介紹了,需要的朋友可以參考下2014-06-06

