0

In Mac OS, the tkinter message boxes do NOT show different icons for different types of message box (other than warning). The error, info, and question icons are all the "Python Spaceship" icon and not specific to errors, info, or questions. See attached files starting with "Screen Shot ..."

In Windows, the message boxes show context sensitive icons. See attached file WindowsMessageBoxOutput.jpg

How do I get the context sensitive icons to load on Mac OS?

The code I used for generating/showing the message boxes is the following:

import tkinter as tk
import tkinter.messagebox as tkmb
from tkinter import Button

def show_message_boxes():
    tkmb.showinfo(title='Info Box', message='Info with info icon', icon='info')
    tkmb.showinfo(title='Info Box', message='Info with error icon', icon='error')
    tkmb.showinfo(title='Info Box', message='Info with question icon', icon='question')
    tkmb.showinfo(title='Info Box', message='Info with warning icon', icon='warning')

    tkmb.showinfo(title='Info Box', message='Info box with info icon', icon='info')
    tkmb.showerror(title='Error Box', message='Error box with default icon', icon='error')
    tkmb.showwarning(title='Warning Box', message='Warning box with default icon', icon='warning')

    tkmb.showinfo(title='Info Box', message='Info box with default icon')
    tkmb.showerror(title='Error Box', message='Error box with default icon')
    tkmb.showwarning(title='Warning Box', message='Warning box with default icon')

window = tk.Tk()

but = Button(window, text ='Click', command = show_message_boxes, width=20, height=10)
but.grid(row=0, column=0)

window.mainloop()

Note: I tried various options to try and generate message boxes with icons (hence the various calls in the code above).

Environment

I'm running with the following on Mac OS:

  • Mojave 10.14.6
  • Python 3.7.5
  • tkinter 8.5

Images:

MacOS Message Boxes Windows Message Boxes

Dude Rat
  • 41
  • 1
  • 5
  • Try .showinfo(title='Info Box', message='Info with info icon', bitmap="info") – stovfl Jan 08 '20 at 11:03
  • @stovfl Not sure why my prior comment disappeared. Apologies if this is a duplicate. The above code sample tries exactly what you are suggesting, (the third from last message box call) On Mac OS the icon problem is still there - no info icon shows. – Dude Rat Jan 09 '20 at 16:10
  • @stovfl Bitmap does not solve the problem and causes an error on Windows and on Mac. I added the following line: tkmb.showinfo(title='Info Box', message='Info with info icon', bitmap='info') Net result is the below error message. Can't give it to you in full because of size limitations. _tkinter.TclError: bad option "-bitmap": must be -default, -detail, -icon, -message, -parent, -title, -type, or -command – Dude Rat Jan 17 '20 at 01:14

2 Answers2

4

I can confirm that this happens on MacOS at least in Big Sur in Python 3.9.9 and 3.10.4.

The only fix I found was to - only in macos! -change the app icon before the call to the messagebox as suggested in How to correct picture tkinter messagebox tkinter on macos and back after the call to messagebox.

I've tried to wrap this behaviour in a python decorator 'if_mac_set_icon' for a clean appearance. The program needs some supplied images in a folder 'images'. See the code for details. Tested on Big Sur and Windows (decorator does nothing there).

from tkinter import Tk, Tcl, Button, messagebox, PhotoImage
from tkinter import ttk
import sys
"""
On MacOS Big Sur using Python 3.9.3:
- messagebox.showwarning() shows yellow exclamationmark with small rocket icon
- showerror(),askretrycancel,askyesno,askquestion, askyesnocancel
On MacOS BigSur using Python 3.10.4 same but with a folder icon instead 
of the rocket item. Tcl/Tk version is 8.6.12 """


# use a decorator with a parameter to add pre and postrocessing
# switching the iconphoto of the root/app see
# https://stackoverflow.com/questions/51530310/how-to-correct-picture-tkinter-messagebox-tkinter-on-macos
# decorator info: see https://realpython.com/primer-on-python-decorators/
def if_mac_set_icon(icon):
    def set_icon(icon):
     """ this function needs a folder 'images' with images with the below 
     names like app.png"""
        images = dict(
            app="app.png",
            info="exclamation.png",
            warning="exclamation.png",
            question="question.png",
            error="error.png"
        )
        img = PhotoImage(file=f"images/{images[icon]}")
        root.iconphoto(False, img)

    def decorator_func(original_func):
        def wrapper_func(*args, **kwargs):
            if sys.platform == "darwin":
                set_icon(icon)
                result = original_func(*args, **kwargs)
                set_icon('app')  # restore app icon
                return result
        return wrapper_func
    return decorator_func


@if_mac_set_icon('warning')
def showwarning(*args, **kwargs):
    return messagebox.showwarning(*args, **kwargs)


@if_mac_set_icon('question')
def askquestion(*args, **kwargs):
    return messagebox.askquestion(*args, **kwargs)


@if_mac_set_icon('error')
def showerror(*args, **kwargs):
    return messagebox.showerror(*args, **kwargs)


@if_mac_set_icon('question')
def askretrycancel(*args, **kwargs):
    return messagebox.askretrycancel(*args, **kwargs)


@if_mac_set_icon('question')
def askyesno(*args, **kwargs):
    return messagebox.askyesno(*args, **kwargs)


root = Tk()

ttk.Button(root, text="Warningbox", command=showwarning).grid()
ttk.Button(root, text="Questionbox", command=askquestion).grid()
ttk.Button(root, text="Errorbox", command=lambda: askquestion(message="Error")).grid()

root.mainloop()

  • The "restore app icon" step will never be reached because of the return above it. The code should be changed to save the result in a variable first, rather than return it right away. Then do the if-darwin/restore, then return the saved result. (The edit queue on this answer is full, so I can't edit it myself.) – ecp Oct 20 '22 at 19:58
  • Can confirm that this behaviour is still existent on macOS Ventura with python3.11.2; Above fix works just perfect. Thanks for sharing. – alexrjs Apr 02 '23 at 19:18
1

FWIW, I see the same behavior on:

  • OS 10.15.5
  • Python 3.8.3
  • tkinter 8.6

Works as expected on Windows & Linux and I can override the default messagebox icon type with the "icon" parameter.

Looks like it's been an issue for some time now: Why can't I change the icon on a tkMessagebox.askyesno() on OS X?