0

我正在尝试使用 psutil 模块在 Tkinter 中创建一个电池通知器。我是Tkinter的新手,不知道如何解决这个特殊问题。

这是我的代码

from tkinter import *
import psutil

root = Tk()
root.title('Battery Notifier')
root.geometry('400x200')
flagBoth = IntVar()
flagBoth.set(0)

flagLow = IntVar()
flagLow.set(0)

flagCharge = IntVar()
flagCharge.set(0)

def batteryLow(percent, xoffset, yoffset):
    lowTop = Toplevel(root)
    lowTop.geometry('419x116+' + str(xoffset) + '+' + str(yoffset))
    lowTop.wm_overrideredirect(True)
    lowTop.attributes('-topmost', 'True')
    lowLabel = Label(lowTop, image=lowPercentImage, borderwidth=0).place(x=0, y=0)
    percentLabel = Label(lowTop, text=percent, font=('Sofia Pro Bold', '20'), borderwidth=0, bg='#fff')
    percentLabel.place(x=76, y=25, width=34)

    # Closing after 5 seconds
    lowTop.after(5000, func=lowTop.destroy)


def batteryCharging(percent, xoffset, yoffset):
    chargeTop = Toplevel(root)
    chargeTop.geometry('419x116+'  + str(xoffset) + '+' + str(yoffset))
    chargeTop.wm_overrideredirect(True)
    chargeTop.attributes('-topmost', 'True')
    chargeLabel = Label(chargeTop, image=batteryChargingImage, borderwidth=0).place(x=0, y=0)
    percentLabel = Label(chargeTop, text=percent, font=('Sofia Pro Bold', '20'), borderwidth=0, bg='#fff')
    percentLabel.place(x=99, y=58, width=34)

    # Closing after 7 seconds
    chargeTop.after(7000, func=chargeTop.destroy)


def batteryStatus():
    battery = psutil.sensors_battery()
    percent = battery.percent
    chargeStatus = battery.power_plugged
    critical = 90
    if (percent < critical and not(flagLow.get())):
        batteryLow(percent, 930, 30)
        flagLow.set(1)
        if chargeStatus:
            batteryCharging(percent, 930, 150)
            flagBoth.set(1)
        
    elif (chargeStatus and flagCharge.get()):
        batteryCharging(percent, 930, 30)
        flagCharge.set(1)

    else:
        if chargeStatus == False and flagLow == 1:
            flagLow.set(0)


    root.after(1000, batteryStatus)


btn = Button(root, text='check', command=exit).pack()

lowPercentImage = PhotoImage(file='D:\\SE4\\Python\\Codes\\MiniProject\\Low Battery.png')
batteryChargingImage = PhotoImage(file='D:\\SE4\\Python\\Codes\\MiniProject\\Battery Charging.png')


root.after(1000, batteryStatus)
root.mainloop()

在此我试图在我的电池百分比低于临界值时获得弹出通知,然后将出现弹出通知。如果同时连接了充电器,它将显示充电器连接的弹出通知,然后在一段时间后消失,就像在Windows 等操作系统中发生的那样。之后,如果我的充电器断开连接并且电池电量低于临界水平,则再次显示电池电量不足弹出通知并消失,否则检查电池电量不足或充电情况(如果发生),然后再次显示弹出通知。

在这个问题中,我不能使用循环,因为它会使 tkinter 冻结。所以我会在 1 秒后一次又一次地调用函数batteryStatus 。谁能告诉我如何解决这个特殊问题。我只想要一个电池通知器,就像它在 Windows 中一样,当电池电量达到 12% 时,它会在连接充电器时显示通知,它会消失,当我移除充电器并且电池电量不足时,它会再次显示通知。

提前致谢。

这是低通知图片

这是电池充电通知图片

这就是我想要弹出通知的方式,一段时间后它们会消失。

4

1 回答 1

0

这是你想做的事吗?(测试运行代码):

from tkinter import Tk, Label
import time


def loop_notification(counter=0):
    if 70 > counter > 50:
        root.deiconify()
        root.overrideredirect(True)
    elif counter > 70:
        root.withdraw()
        counter = 0
    counter += 1
    root.after(100, loop_notification, counter)


root = Tk()
root.attributes('-topmost', True)
root.geometry(f'400x100+{root.winfo_screenwidth() - 400}+{root.winfo_screenheight() - 100}')
root.withdraw()

Label(root, text='Notification', font='default 20 bold').pack(pady=10)
Label(root, text='Notification body here', font='default 12 normal').pack(pady=5)

loop_notification()

root.mainloop()

我希望你明白循环显然可以替换为你所拥有的并且你不一定需要使用线程这只是一个例子

'-topmost'确保窗口位于其他窗口之上,隐藏overrideredirect窗口周围的框架

于 2021-04-18T04:04:52.003 回答