Python Tkinter GUI-使用after()在GUI的后台运行函数

时间:2018-10-28 11:48:19

标签: python user-interface tkinter sqlite

我正在用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()

0 个答案:

没有答案