python - 每 x 分钟创建一个 tkinter 窗口,然后在 y 秒后自动关闭它

标签 python multithreading tkinter

我正在尝试构建一个简单的程序来提醒我在使用计算机时休息一下。我对 python 有一定的了解,但以前从未玩过 GUI 编程或线程,因此以下内容实质上是从 stackoverflow 复制/粘贴:

import threading
import time
import Tkinter

class RepeatEvery(threading.Thread):
    def __init__(self, interval, func, *args, **kwargs):
        threading.Thread.__init__(self)
        self.interval = interval  # seconds between calls
        self.func = func          # function to call
        self.args = args          # optional positional argument(s) for call
        self.kwargs = kwargs      # optional keyword argument(s) for call
        self.runable = True

    def run(self):
        while self.runable:
            self.func(*self.args, **self.kwargs)
            time.sleep(self.interval)

    def stop(self):
        self.runable = False

def microbreak():
    root = Tkinter.Tk()
    Tkinter.Frame(root, width=250, height=100).pack()
    Tkinter.Label(root, text='Hello').place(x=10, y=10)
    threading.Timer(3.0, root.destroy).start()
    root.mainloop()
    return()

thread = RepeatEvery(6, microbreak)
thread.start()

这给了我第一个中断通知,但在给我第二个中断通知之前失败了。

Tcl_AsyncDelete: async handler deleted by the wrong thread

fish: Job 1, “python Documents/python/timer/timer.py ” terminated by signal SIGABRT (Abort)

有什么想法吗?我很高兴使用 tkinter 以外的其他东西来实现 gui-stuff,或者使用线程以外的其他东西来实现时间。


根据下面的答案,我的新工作脚本如下:

import Tkinter as Tk
import time

class Window:
    def __init__(self):
        self.root = None
        self.hide = 10 #minutes
        self.show = 10 #seconds

    def close(self):
        self.root.destroy()
        return

    def new(self):
        self.root = Tk.Tk()
        self.root.overrideredirect(True)
        self.root.geometry("{0}x{1}+0+0".format(self.root.winfo_screenwidth(), self.root.winfo_screenheight()))
        self.root.configure(bg='black')
        Tk.Label(self.root, text='Hello', fg='white', bg='black', font=('Helvetica', 30)).place(anchor='center', relx=0.5, rely=0.5)
        #Tk.Button(text = 'click to end', command = self.close).pack()
        self.root.after(self.show*1000, self.loop)

    def loop(self):
        if self.root:
            self.root.destroy()
        time.sleep(self.hide*60)
        self.new()
        self.root.mainloop()
        return

Window().loop()

最佳答案

我认为如果没有线程,你会更容易实现这一点,Tkinter 不能很好地集成。相反,您可以使用 afterafter_idle 方法来安排回调在特定超时后运行。您可以创建一种方法来显示窗口并安排它隐藏,另一种方法隐藏窗口并安排它显示。然后他们就会在无限循环中互相调用:

import tkinter

class Reminder(object):
    def __init__(self, show_interval=3, hide_interval=6):
        self.hide_int = hide_interval  # In seconds
        self.show_int = show_interval  # In seconds
        self.root = Tkinter.Tk()
        tkinter.Frame(self.root, width=250, height=100).pack()
        tkinter.Label(self.root, text='Hello').place(x=10, y=10)
        self.root.after_idle(self.show)  # Schedules self.show() to be called when the mainloop starts

    def hide(self):
        self.root.withdraw()  # Hide the window
        self.root.after(1000 * self.hide_int, self.show) # Schedule self.show() in hide_int seconds

    def show(self):
        self.root.deiconify() # Show the window
        self.root.after(1000 * self.show_int, self.hide)  # Schedule self.hide in show_int seconds

    def start(self):
        self.root.mainloop()

if __name__ == "__main__":
    r = Reminder()
    r.start()

关于python - 每 x 分钟创建一个 tkinter 窗口,然后在 y 秒后自动关闭它,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25007961/

相关文章:

multithreading - 在后台和线程中加载 JavaFX 图像

java - Android:处理同步网络通话

python - 如何隐藏 Tkinter python Gui

python - 为什么当我从网页上抓取价格时,我会得到一个 ?用 python ?

python - 如何按 3 列打印 2 本词典

python - 如何将Butterworth过滤器应用于我的代码?

c# - 计时器是否创建新线程?

Python 列表理解从列表中删除元素和下一个元素

Python、Tkinter、tkFont : Label resize

python - tkinter 程序的窗口大小