我正在用Tkinter制作GUI,以支持用于嵌入式系统课程的帕金森震颤监测系统。这是我第一次使用Python,也是我第一次进行面向对象的编程,因此请原谅我可能糟糕的代码和实践。我当前的程序是一些StackOverflow Q / A和我自己的功能的组合。我见过人们在问一些类似的问题,答案通常是使用多线程或使用after(),但我试图避免使用多线程,如果可能的话,我目前的问题是我对after()的使用是达到我的期望。
基本上,目标是用户可以输入药物(名称,剂量和频率),然后将其存储在SQLite数据库中。当需要服用存储在数据库中的一种药物时(由输入的“频率”参数确定的时间),它应触发一个切换页面,指示用户服用该药物(MedAlert框架)。检查是否需要切换,其余的GUI应该正常运行。
我的闹钟功能在这里:
## Function to alert the user to take medication
def alarm(self):
## Import data
medData = self.retrieve_data()
## Seperate rows
i = 0
for row in medData:
name, dose, freq, startTime, waitTime = str(row).split(",")
array_startTime.append((startTime.replace("'","")).strip())
array_waitTime.append((waitTime.replace("'","")).replace(")",""))
## For each medication, check if it's time to take it
if (datetime.datetime.now() == datetime.datetime.strptime(array_startTime[i], '%Y-%m-%d %H:%M:%S') + datetime.timedelta(minutes = float(array_waitTime[i]))):
self.switch_frame(MedAlert)
i += 1
.replace()、. strip()等仅用于从检索到的SQLite数据中删除不必要的标点符号。目的是使此功能在后台持续运行,以便一旦检测到需要服用存储在数据库中的药物,便会在GUI中切换框架。我目前正在使用after()函数,如下所示:
if __name__ == "__main__":
gui = PDAS_GUI()
gui.after(0, gui.alarm())
gui.mainloop()
我可以执行所有操作,输入/删除药物,使用GUI,但从未触发过MedAlert屏幕(使用输入频率0.01小时[36秒]进行了测试。输出完全没有错误。是问题所在借助我的alarm()函数本身,或者我尝试运行它的方式,非常感谢你们提供的任何帮助/指导!完整代码如下:
import tkinter as tk
from tkinter import font as tkfont
import sqlite3
import time
import datetime
conn = sqlite3.connect('PDAS_db.sqlite')
cur = conn.cursor()
cur.execute('CREATE TABLE IF NOT EXISTS medication (name VARCHAR, dose VARCHAR, freq VARCHAR, startTime VARCHAR, waitTime VARCHAR)')
conn.commit()
conn.close()
array_startTime = []
array_waitTime = []
class PDAS_GUI(tk.Tk):
## Function for initialisation
def __init__(self):
tk.Tk.__init__(self)
self.frame = None
self.switch_frame(Home)
## Global temp variables for data entry
self.shared_vars = {
"MedName": tk.StringVar(),
"MedDose": tk.StringVar(),
"MedFreq": tk.StringVar(),
}
## Function to switch between frames
def switch_frame(self, frame_class):
new_frame = frame_class(self)
if self.frame is not None:
self.frame.destroy()
self.frame = new_frame
self.frame.pack()
## Function to store data to SQLite database
def store_data(self, name, dose, freq):
startTime = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")
waitTime = (float(freq) * 60)
conn = sqlite3.connect('PDAS_db.sqlite')
cur = conn.cursor()
cur.execute('INSERT INTO medication (name, dose, freq, startTime, waitTime) VALUES (?, ? ,?, ?, ?)',
(str(name), str(dose), str(freq), str(startTime), str(waitTime)))
conn.commit()
conn.close()
## Function to retrieve data from SQLite database
def retrieve_data(self):
conn = sqlite3.connect('PDAS_db.sqlite')
cur = conn.cursor()
cur.execute('SELECT * FROM medication')
medData = cur.fetchall()
conn.close()
return medData
## Function to alert the user to take medication
def alarm(self):
## Import data
medData = self.retrieve_data()
## Seperate rows
i = 0
for row in medData:
name, dose, freq, startTime, waitTime = str(row).split(",")
array_startTime.append((startTime.replace("'","")).strip())
array_waitTime.append((waitTime.replace("'","")).replace(")",""))
## For each medication, check if it's time to take it
if (datetime.datetime.now() == datetime.datetime.strptime(array_startTime[i], '%Y-%m-%d %H:%M:%S') + datetime.timedelta(minutes = float(array_waitTime[i]))):
self.switch_frame(MedAlert)
i += 1
## Home Page
class Home(tk.Frame):
def __init__(self, master):
tk.Frame.__init__(self, master)
tk.Label(self, text = 'PARKINSONS DISEASE ASSISTANCE SYSTEM').pack(side = 'top', fill = 'x' , pady = 10)
tk.Button(self, text = 'Medication',
command = lambda: master.switch_frame(Medication2)).pack()
## Page to enter new medications
class Medication2(tk.Frame):
def __init__(self, master):
tk.Frame.__init__(self, master)
tk.Label(self, bd = 50, text="Add New Medication").grid(row = 0, column =1)
tk.Label(self, bd = 100, text="Medication Name:").grid(row=1, column = 0)
MedName = tk.Entry(self, textvariable=self.master.shared_vars["MedName"])
MedName.grid(row = 1, column = 1)
tk.Label(self, bd = 100, text="Dosage:").grid(row=2, column = 0)
MedDose = tk.Entry(self, textvariable=self.master.shared_vars["MedDose"])
MedDose.grid(row = 2, column = 1)
tk.Label(self, bd = 100, text="Frequency (hours):").grid(row=3, column = 0)
MedFreq = tk.Entry(self, textvariable=self.master.shared_vars["MedFreq"])
MedFreq.grid(row = 3, column = 1)
tk.Button(self, text = "Finish",
command = lambda: master.switch_frame(Medication4)).grid(row = 4, column = 1)
## Page that confirms & stores new medications
class Medication4(tk.Frame):
def __init__(self, master):
tk.Frame.__init__(self, master)
tk.Label(self, text="Verify New Medication").grid(row = 0 , column = 1)
MedName = self.master.shared_vars["MedName"].get()
MedDose = self.master.shared_vars["MedDose"].get()
MedFreq = self.master.shared_vars["MedFreq"].get()
tk.Label(self, text = "Please confirm your new medication:\nMedication Name: %s\n Dosage: %s\n Frequency: %s\n" % (MedName, MedDose, MedFreq)).grid(row = 1, column = 1)
tk.Button(self, text = "Confirm & Return Home",
command=lambda: [master.switch_frame(Home), master.store_data(MedName, MedDose, MedFreq)]).grid(column = 1)
## Alarm page
class MedAlert(tk.Frame):
def __init__(self, master):
tk.Frame.__init__(self, master)
tk.Label(self, text = "Medication Alert!\n\n Take %s of %s." % (str(dose),str(name))).grid(row = 0 , column = 0)
tk.Button(self, text = "Medication Taken",
command = lambda: master.switch_frame(Home)).grid(row = 1 , column = 0)
## Run the program
if __name__ == "__main__":
gui = PDAS_GUI()
gui.after(0, gui.alarm())
gui.mainloop()