import tkinter as tk import multiprocessing class balloon_class: def __init__(self, queue, message, x, y, font_name, font_size, fore_color, back_color, transparency, show_border): self.process = multiprocessing.Process(target=self.create_balloon, daemon=True, args=(queue,message,x,y,font_name,font_size,fore_color,back_color,transparency, show_border)) self.process.start() def create_balloon(self, queue, message, x, y, font_name, font_size, fore_color, back_color, transparency, show_border): self.root = tk.Tk() self.root.withdraw() self.root.wm_overrideredirect(True) self.sub_window = tk.Toplevel(self.root) self.sub_window.deiconify() if show_border: border = 'solid' else: border = 'flat' #サイズ計算用のラベル self.dummy_label = tk.Label(self.sub_window, text=message, font=(font_name, font_size)) # ラベルサイズを計算 width = self.dummy_label.winfo_reqwidth() height = self.dummy_label.winfo_reqheight() self.sub_window.attributes("-topmost", True) # 全体を半透明にする(ウィンドウ全体が透明度を持つ) self.sub_window.wm_attributes("-alpha", transparency) self.sub_window.geometry(f"{width+20}x{height+20}+{x}+{y}") self.sub_window.configure(bg=back_color) self.frame = tk.Frame(self.sub_window, bg=back_color, bd=1, relief=border) self.frame.place(x=0, y=0, width=width+20, height=height+20) self.label = tk.Label(self.frame, text=message, fg=fore_color, bg=back_color, font=(font_name, font_size), justify="left") self.label.place(x=8, y=10, width=width, height=height) self.sub_window.wm_overrideredirect(True) self.update_balloon(queue, message, x, y, font_name, font_size, fore_color, back_color, transparency, show_border) self.root.mainloop() def update_balloon(self, queue, message, x, y, font_name, font_size, fore_color, back_color, transparency, show_border): try: while not queue.empty(): # キューからデータを取得してGUIの内容を更新 balloon_args, hide = queue.get_nowait() message, x, y, font_name, font_size, fore_color, back_color, transparency, show_border = balloon_args try: if hide: self.sub_window.withdraw() else: self.sub_window.deiconify() except Exception: # ウィンドウをAlt+F4で消した場合も再生成 self.sub_window = tk.Toplevel(self.root) self.sub_window.wm_overrideredirect(True) self.sub_window.deiconify() self.dummy_label = tk.Label(self.sub_window) self.frame = tk.Frame(self.sub_window) self.label = tk.Label(self.frame) if show_border: border = 'solid' else: border = 'flat' self.dummy_label.config(text=message, font=(font_name, font_size)) width = self.dummy_label.winfo_reqwidth() height = self.dummy_label.winfo_reqheight() self.sub_window.wm_attributes("-alpha", transparency) self.sub_window.geometry(f"{width+20}x{height+20}+{x}+{y}") self.sub_window.configure(bg=back_color) self.frame.config(bg=back_color, bd=1, relief=border) self.frame.place(x=0, y=0, width=width+20, height=height+20) self.label.config(text=message, fg=fore_color, bg=back_color, font=(font_name, font_size), justify="left") self.label.place(x=8, y=10, width=width, height=height) except: pass self.root.after(1, self.update_balloon, queue, message, x, y, font_name, font_size, fore_color, back_color, transparency, show_border) def balloon(message=" ", x=0, y=0, font_name="Arial", font_size=14, fore_color="#000000", back_color="#FFFF00", transparency=1, show_border=True): global balloon_process, balloon_queue if 'balloon_process' not in globals() or not balloon_process.process.is_alive(): balloon_queue = multiprocessing.Queue() balloon_process=balloon_class(balloon_queue, message, x, y, font_name, font_size, fore_color, back_color, transparency, show_border) else: balloon_args = [message, x, y, font_name, font_size, fore_color, back_color, transparency, show_border] hide = False balloon_queue.put((balloon_args, hide)) def hide_balloon(): try: dummy_args = [" ", 0, 0, "Arial", 14, "#000000", "#FFFF00", 1, True] hide = True balloon_queue.put((dummy_args, hide)) except Exception: pass if __name__ == "__main__": import time balloon(message="Hello World!\nThis is a test message.\nこんにちは", x=300, y=500, font_name="Arial", font_size=14, fore_color="#000000", back_color="#00FFFF", transparency=0.7, show_border=False) time.sleep(3) time.sleep(1) balloon(message="Updated Content!", x=300, y=500, font_size=14, back_color="#00FFFF", transparency=0.7, show_border=False) time.sleep(3) balloon(message="Final Update!", x=300, y=500, font_size=14, back_color="#00FFFF", transparency=0.7, show_border=True) time.sleep(3)