在屏幕上显示控制台

Display console on screen

所以我有一个基本的警报 python GUI,没有什么花哨的东西仍然需要大量的工作。所以目前我的代码如下:用户点击“创建新闹钟”,它会打开一个 window 和 3 个选项菜单小部件,并选择他希望闹钟响起的时间,然后一旦设置的闹钟被点击loop 是 运行 每次重复循环并在控制台打印时间时倒计时一秒,而不是当他们设置的时间等于闹钟响起的当前时间时。

现在我的问题是我希望控制台中的倒计时显示在 GUI 上。我试图简单地制作一个标签并使用 .get 来获取当前值并显示它们但是一旦循环开始它就不会执行任何其他代码。如果我有任何其他建议,我会洗耳恭听。我想要的只是一个倒计时,显示闹钟响起的时间,我目前在试错计划中的想法是显示控制台。

这是我的代码:

# Import Required Library
from tkinter import *
import datetime
import time
import winsound
from threading import *
from tkinter import messagebox

def submit():

    def alarm(Curent):
        # Infinite Loop
        while True:
            # Set Alarm
            set_alarm_time = f"{hour.get()}:{minute.get()}:{second.get()}"

            # Wait for one seconds
            time.sleep(1)

            # Get current time
            current_time = datetime.datetime.now().strftime("%H:%M:%S")
            print(current_time,set_alarm_time)

            Curent = current_time
            set = set_alarm_time


            # Check whether set alarm is equal to current time or not
            if current_time == set_alarm_time:
                print("Time to Wake up")
                # Playing sound
                winsound.PlaySound("sound.wav",winsound.SND_ASYNC)
                messagebox.showinfo(title="ALARM", message="Alarm is going off, its time to wake up!")
                break


    root = Tk()
    root.geometry("400x300")
    root.config(bg="#447c84")
    root.title('MathAlarm')

    # Add Labels, Frame, Button, Optionmenus
    Label(root,text="Alarm Clock",font=("Helvetica 20 bold"),fg="Black").pack(pady=10)
    Label(root,text="Set Time",font=("Helvetica 15 bold")).pack()

    frame = Frame(root)
    frame.pack()

    hour = StringVar(root)
    hours = ('00', '01', '02', '03', '04', '05', '06', '07',
            '08', '09', '10', '11', '12', '13', '14', '15',
            '16', '17', '18', '19', '20', '21', '22', '23', '24'
            )
    hour.set(hours[0])

    hrs = OptionMenu(frame, hour, *hours)
    hrs.pack(side=LEFT)

    minute = StringVar(root)
    minutes = ('00', '01', '02', '03', '04', '05', '06', '07',
            '08', '09', '10', '11', '12', '13', '14', '15',
            '16', '17', '18', '19', '20', '21', '22', '23',
            '24', '25', '26', '27', '28', '29', '30', '31',
            '32', '33', '34', '35', '36', '37', '38', '39',
            '40', '41', '42', '43', '44', '45', '46', '47',
            '48', '49', '50', '51', '52', '53', '54', '55',
            '56', '57', '58', '59', '60')
    minute.set(minutes[0])

    mins = OptionMenu(frame, minute, *minutes)
    mins.pack(side=LEFT)

    second = StringVar(root)
    seconds = ('00', '01', '02', '03', '04', '05', '06', '07',
            '08', '09', '10', '11', '12', '13', '14', '15',
            '16', '17', '18', '19', '20', '21', '22', '23',
            '24', '25', '26', '27', '28', '29', '30', '31',
            '32', '33', '34', '35', '36', '37', '38', '39',
            '40', '41', '42', '43', '44', '45', '46', '47',
            '48', '49', '50', '51', '52', '53', '54', '55',
            '56', '57', '58', '59', '60')
    second.set(seconds[0])

    secs = OptionMenu(frame, second, *seconds)
    secs.pack(side=LEFT)

    Button(root,text="Set Alarm",font=("Helvetica 15"),command=alarm).pack(pady=20)
    Button(root,text="Exit",font=("Helvetica 15"), command=lambda:root.destroy()).pack(pady=20)

root = Tk()
root.title('MathAlarm')
root.geometry('347x400')
root.config(bg="#447c84")

welcomelabel = Label(root, text="Welcome to Math Alarm", font=("Times", "24", "bold"))
welcomelabel.pack()

ext = Button(root, text="Exit", padx=20, pady=10, relief=SOLID, font=("Times", "14", "bold"), command=lambda:root.destroy())
reg = Button(root, text="Create new Alarm", padx=20, pady=10, relief=SOLID, font=("Times", "14", "bold"), command=submit)
ext.pack()
reg.pack()

# Execute Tkinter
root.mainloop()`

好吧,我尝试了一种完全不使用自定义线程但使用 tkinter 自己的主循环的不同方法,它也有自己的缺点和优点。我对您的代码进行了以下更改以使其正常工作

  1. 小时、分钟和秒的全局变量
  2. 输出标签的全局变量
  3. 将您的警报功能与提交功能分开
  4. 从按钮命令中删除了警报功能

tkinter 中有一个选项 运行 定期使用 tkinter 主循环的函数,这样你就不会阻塞 tkinter 的任何事件处理或任何其他进程,因为 tkinter 本身会处理查看 root.after(time, function) 的文档以获取更多详细信息。

# Import Required Library
from tkinter import *
import datetime
import time
import winsound
from threading import *
from tkinter import messagebox

mainLabel = None
(h, m, s) = (None, None, None)
root = None

def alarm():
    global mainLabel
    
    set_alarm_time = f"{h}:{m}:{s}"
    current_time = datetime.datetime.now().strftime('%H:%M:%S')

    mainLabel['text'] = current_time #update current time in label, you can show whatever you want
    print(current_time, set_alarm_time)

    # Check whether set alarm is equal to current time or not
    if current_time == set_alarm_time:
        print("Time to Wake up")
        # Playing sound
        winsound.PlaySound("sound.wav", winsound.SND_ASYNC)
        messagebox.showinfo(title="ALARM", message="Alarm is going off, its time to wake up!")
        #no more need to schedule the function 
    else:
        #alarm time is not reached let's schedule the function again for one second
        root.after(1000, alarm)

def submit():
    global mainLabel
    
    def start():
        global h, m, s, hours, mins, secs
        
        print('scheduling alarm')
        h = hour.get()
        m = minute.get()
        s = second.get()
        (hours, mins, secs) = (int(h), int(m), int(s))
        root.after(1000, alarm)
        
    root = Tk()
    root.geometry("400x300")
    root.config(bg="#447c84")
    root.title('MathAlarm')

    # Add Labels, Frame, Button, Optionmenus
    Label(root,text="Alarm Clock",font=("Helvetica 20 bold"),fg="Black").pack(pady=10)
    mainLabel = Label(root,text="Set Time",font=("Helvetica 15 bold"))
    mainLabel.pack()
    
    frame = Frame(root)
    frame.pack()

    hour = StringVar(root)
    hours = ('00', '01', '02', '03', '04', '05', '06', '07',
            '08', '09', '10', '11', '12', '13', '14', '15',
            '16', '17', '18', '19', '20', '21', '22', '23', '24'
            )
    hour.set(hours[0])

    hrs = OptionMenu(frame, hour, *hours)
    hrs.pack(side=LEFT)

    minute = StringVar(root)
    minutes = ('00', '01', '02', '03', '04', '05', '06', '07',
            '08', '09', '10', '11', '12', '13', '14', '15',
            '16', '17', '18', '19', '20', '21', '22', '23',
            '24', '25', '26', '27', '28', '29', '30', '31',
            '32', '33', '34', '35', '36', '37', '38', '39',
            '40', '41', '42', '43', '44', '45', '46', '47',
            '48', '49', '50', '51', '52', '53', '54', '55',
            '56', '57', '58', '59', '60')
    minute.set(minutes[0])

    mins = OptionMenu(frame, minute, *minutes)
    mins.pack(side=LEFT)

    second = StringVar(root)
    seconds = ('00', '01', '02', '03', '04', '05', '06', '07',
            '08', '09', '10', '11', '12', '13', '14', '15',
            '16', '17', '18', '19', '20', '21', '22', '23',
            '24', '25', '26', '27', '28', '29', '30', '31',
            '32', '33', '34', '35', '36', '37', '38', '39',
            '40', '41', '42', '43', '44', '45', '46', '47',
            '48', '49', '50', '51', '52', '53', '54', '55',
            '56', '57', '58', '59', '60')
    second.set(seconds[0])

    secs = OptionMenu(frame, second, *seconds)
    secs.pack(side=LEFT)

    Button(root,text="Set Alarm",font=("Helvetica 15"), command=start).pack(pady=20)
    Button(root,text="Exit",font=("Helvetica 15"), command=lambda:root.destroy()).pack(pady=20)

root = Tk()
root.title('MathAlarm')
root.geometry('347x400')
root.config(bg="#447c84")

welcomelabel = Label(root, text="Welcome to Math Alarm", font=("Times", "24", "bold"))
welcomelabel.pack()

ext = Button(root, text="Exit", padx=20, pady=10, relief=SOLID, font=("Times", "14", "bold"), command=lambda:root.destroy())
reg = Button(root, text="Create new Alarm", padx=20, pady=10, relief=SOLID, font=("Times", "14", "bold"), command=submit)
ext.pack()
reg.pack()

root.mainloop()

输出如下

注意:答案仅用于展示,如何在 GUI 中更新 tkinter 的标签值,这是实际问题。