我正在使用Tkinter和Python制作时钟。
我要实现的是运行时钟并自动检查JSON文件(包含时钟的可视设置)是否已更新。如果JSON文件已更新,则时钟将实时更新。
但是,事实并非如此。我要做的是更新JSON文件,关闭时钟程序,然后重新打开时钟程序。只有在这种情况下,更改的JSON设置才会发生。
clock.py
from tkinter import *
from datetime import datetime
from settings import *
# Updates the program and clock settings
def tick():
time_string = datetime.now().strftime(time_format)
date_string = datetime.now().strftime(date_format)
root.config(bg=background_color)
container.configure(bg=background_color)
current_time.configure(text=time_string,
font=(time_font, time_size, time_weight, time_slant),
fg=time_color,
bg=background_color)
current_date.configure(text=date_string,
font=(date_font, date_size, date_weight, date_slant),
fg=date_color,
bg=background_color)
current_time.after(1, tick)
# TKInterface
root = Tk()
root.title(window_title)
# Binds 'Esc' key to exit program
root.bind('<Escape>', exit)
# Runs program in full-screen
if full_screen:
root.attributes('-fullscreen', True)
root.config(cursor='none')
# Creates container to hold time and date
container = Frame(root)
current_time = Label(container)
current_date = Label(container)
container.pack(expand=True)
current_time.pack()
current_date.pack()
tick()
root.mainloop()
settings.py
import os
import json
with open('settings.json') as json_settings:
settings = json.load(json_settings)
# Window
full_screen = settings['window']['full_screen']
window_title = settings['window']['window_title']
# Background
background_color = settings['background']['color']
# Time
time_font = settings['time']['font']
time_size = settings['time']['size']
time_weight = settings['time']['weight']
time_slant = settings['time']['slant']
time_color = settings['time']['color']
time_format = settings['time']['format']
# Date
date_font = settings['date']['font']
date_size = settings['date']['size']
date_weight = settings['date']['weight']
date_slant = settings['date']['slant']
date_color = settings['date']['color']
date_format = settings['date']['format']
settings.json
{
"window": {
"full_screen": false,
"window_title" : "chronoberry"
},
"background": {
"color": "black"
},
"time": {
"font": "arial",
"size": 70,
"weight": "bold",
"slant": "roman",
"color": "white",
"format": "%-I:%M:%S %p"
},
"date": {
"font": "arial",
"size": 20,
"weight": "normal",
"slant": "roman",
"color": "white",
"format": "%A, %B %-d %Y"
}
}
所需效果:
如果我在JSON文件中更改背景颜色并保存,我的时钟应该能够在运行时更新其颜色。
更改背景颜色之前
更改背景颜色后
我尝试过的事情:
答案 0 :(得分:1)
您的settings
模块本质上是一个常量模块,这使得重用非常困难。虽然您可以做些骇人听闻的事情来迫使reload
像这样:
def tick():
import settings, importlib
importlib.reload(settings)
from settings import *
# ... rest of tick code ...
这将导致效率低下,并且严重滥用导入机制(现在,您不再读取一个文件,而是读取两个文件,即模块和依赖它的JSON)。
相反,我建议使用可以读取数据并缓存数据的函数(而不是一堆全局变量)使settings
更具可重用性:
import os
import json
class Settings:
SETTINGS_FILE = 'settings.json'
def __init__(self):
self._load_settings()
def update_settings(self):
if self._last_update != os.stat(self.SETTINGS_FILE).st_mtime:
self._load_settings()
return True
return False
def _load_settings(self):
with open(self.SETTINGS_FILE) as json_settings:
settings = json.load(json_settings)
self._last_update = os.fstat(json_settings.fileno()).st_mtime
# Window
self.full_screen = settings['window']['full_screen']
self.window_title = settings['window']['window_title']
# Background
self.background_color = settings['background']['color']
# Time
self.time_font = settings['time']['font']
self.time_size = settings['time']['size']
self.time_weight = settings['time']['weight']
self.time_slant = settings['time']['slant']
self.time_color = settings['time']['color']
self.time_format = settings['time']['format']
# Date
self.date_font = settings['date']['font']
self.date_size = settings['date']['size']
self.date_weight = settings['date']['weight']
self.date_slant = settings['date']['slant']
self.date_color = settings['date']['color']
self.date_format = settings['date']['format']
现在,您的clock
模块可以导入settings
,预先构造一个Settings
对象,并在每个tick
上调用update_settings()
。如果update_settings
返回True
,它也应该重新应用配置。该代码需要对各种名称进行限定,因此,您不必输入date_color
,而是输入:
mysettings = Settings()
在最高级别,并使用以下内容引用date_color
:
mysettings.date_color
但这是改善代码所需付出的小代价。
答案 1 :(得分:0)
此代码有多严重?您可以使用os.stat(path_to_file).st_mtime
每隔一定时间检查文件的上次修改时间,如果晚于上次检查的时间,则刷新界面。又快又脏。
答案 2 :(得分:0)
您有两种选择。 benas建议的选项是1。大约每秒钟检查一次json文件的最后修改时间,以查看它是否已更改。
另一种选择是使用诸如PyiNotify之类的软件包。该程序包可以识别在文件和文件夹上发生的事件。 1这样的事件是IN_MODIFY事件,该事件在文件被修改时触发。可以找到事件列表here。
首先,您需要使用pip安装软件包:
pip install pyinotify
以下是示例代码(几乎完全来自其文档)
import pyinotify
# The watch manager stores the watches and provides operations on watches
wm = pyinotify.WatchManager()
wm.add_watch('/path/to/file', mask, rec=True)
mask = pyinotify.IN_MODIFY # watched events
class EventHandler(pyinotify.ProcessEvent):
def process_IN_MODIFY(self, event):
print "Modifying:", event.pathname