Python Tkinter GUI - Использование after () для запуска функции в фоновом режиме GUI - PullRequest
0 голосов
/ 28 октября 2018

Я создаю графический интерфейс с Tkinter для поддержки системы мониторинга тремора Паркинсона для курса по встроенным системам.Я впервые использую Python и впервые занимаюсь объектно-ориентированным программированием, поэтому прошу прощения за мой, вероятно, ужасный код и практики.Моя текущая программа представляет собой смесь некоторых StackOverflow Q / A и моих собственных функций.Я видел, как люди задают несколько похожих вопросов, и ответ, как правило, был либо многопоточность, либо использование after (), но я стараюсь избегать многопоточности, если это вообще возможно, и моя текущая проблема заключается в том, что мое использование after () не 'т достижения того, чего я ожидаю.

По сути, цель состоит в том, чтобы пользователь мог ввести лекарство (имя, дозировка и частота), которое затем сохраняется в базе данных SQLite.Когда пришло время принимать одно из лекарств, хранящихся в базе данных (время определено введенным параметром «частота»), должно произойти переключение на страницу, инструктирующую пользователя принять это лекарство (кадр MedAlert). Пока программа синхронизирует /проверяя, пора ли переключаться, остальная часть графического интерфейса должна работать нормально.

Моя функция тревоги здесь:

## 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()
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...