mbilal25tr
mbilal25tr

Reputation: 141

Message Bubbles in Windows with Tkinter

I have a program that have shorcuts etc. and can take and save screenshots. Once a screenshot wís saved, I want to show a notification with bubble like: https://tipsfromanand.files.wordpress.com/2011/01/clip_image001.png

How to do it with Tkinter? Is it possible?

Upvotes: 1

Views: 2434

Answers (2)

Taku
Taku

Reputation: 33724

Using tkinter? No, you can't because the bubble notification is only available in Windows while all of (most of) tkinter's widgets are meant to be cross-platform. But to do the task, it's very possible with using the win32api which is an api for windows. You can get all the modules by using pip to install this package: pypiwin32 which includes win32api, win32gui... Here is an example from their source on making the bubble widget you wanted:

from win32api import *
from win32gui import *
import win32con
import sys, os
import struct
import time

class WindowsBalloonTip:
    def __init__(self, title, msg):
        message_map = {
                win32con.WM_DESTROY: self.OnDestroy,
        }
        # Register the Window class.
        wc = WNDCLASS()
        hinst = wc.hInstance = GetModuleHandle(None)
        wc.lpszClassName = "PythonTaskbar"
        wc.lpfnWndProc = message_map # could also specify a wndproc.
        classAtom = RegisterClass(wc)
        # Create the Window.
        style = win32con.WS_OVERLAPPED | win32con.WS_SYSMENU
        self.hwnd = CreateWindow( classAtom, "Taskbar", style, \
                0, 0, win32con.CW_USEDEFAULT, win32con.CW_USEDEFAULT, \
                0, 0, hinst, None)
        UpdateWindow(self.hwnd)
        iconPathName = os.path.abspath(os.path.join( sys.path[0], "balloontip.ico" ))
        icon_flags = win32con.LR_LOADFROMFILE | win32con.LR_DEFAULTSIZE
        try:
           hicon = LoadImage(hinst, iconPathName, \
                    win32con.IMAGE_ICON, 0, 0, icon_flags)
        except:
          hicon = LoadIcon(0, win32con.IDI_APPLICATION)
        flags = NIF_ICON | NIF_MESSAGE | NIF_TIP
        nid = (self.hwnd, 0, flags, win32con.WM_USER+20, hicon, "tooltip")
        Shell_NotifyIcon(NIM_ADD, nid)
        Shell_NotifyIcon(NIM_MODIFY, \
                         (self.hwnd, 0, NIF_INFO, win32con.WM_USER+20,\
                          hicon, "Balloon  tooltip",title,200,msg))
        # self.show_balloon(title, msg)
        time.sleep(10)
        DestroyWindow(self.hwnd)
        UnregisterClass(classAtom, hinst)
    def OnDestroy(self, hwnd, msg, wparam, lparam):
        nid = (self.hwnd, 0)
        Shell_NotifyIcon(NIM_DELETE, nid)
        PostQuitMessage(0) # Terminate the app.
def balloon_tip(title, msg):
    w=WindowsBalloonTip(msg, title)

balloon_tip('Hello', 'How are you?')

If you insist on using tkinter, the closest thing you can get is using tkinter's messagebox: Here's a few examples:

import tkinter as tk
from tkinter import messagebox as tkMessageBox

# hide main window
root = tk.Tk()
root.withdraw()

tkMessageBox.showerror("Error", "Error message")
tkMessageBox.showwarning("Warning","Warning message")
tkMessageBox.showinfo("Information","Informative message")

But I would still recommend using the win32api since this is what your question's asking for.

EDIT

If you're using the first example with tkinter, you will need to first import threading then replace balloon_tip('Hello', 'How are you?') with this:

balloon_thread = threading.Thread(target=balloon_tip, args=('Hello', 'How are you?'))
balloon_thread.start()

when trying to start the bubble, since the program gets paused when using win32api and tkinter will react with being unresponsive.

Note: this guide is specifically designed for python 3 since many of the modules are named differently in python 2.

Upvotes: 1

Stijn Van Daele
Stijn Van Daele

Reputation: 295

All possible widgets offered by tkinter are offered on their site. As far as I am aware no bubbles exist and a label is the closest thing. http://effbot.org/tkinterbook/tkinter-index.htm

One possible solution:

import os
import time
from tkinter import *


fname = "C:\\Users\\...\\test.txt"


while not a:
    time.sleep(1)
    a = os.path.isfile(fname) 


def Notification(master):

    w = Label(master, text="Hello, world!")
    w.pack()
    mainloop()


master = Tk()
Notification(master)

Here you have a while loop checking if you have added a new file. You can change the name dynamically if you want. Once the file is found, a tkinter widget pops up. You can change the location where the widget pops up.

Upvotes: 0

Related Questions