How can I add a "show details" button to a tkinter messagebox? How can I add a "show details" button to a tkinter messagebox? tkinter tkinter

How can I add a "show details" button to a tkinter messagebox?


I would use a Toplevel() window to build my own customer error box.

I think using ttk buttons here would be a good idea and with a combination of frames and weights we can get the window to look decent enough.

Keeping the window from being resized by the user I also had to set up a way to toggle the details textbox. With a tracking variable and the use of a if/else statement that was easy enough to set up.

Finally, we can disable the textbox with .config(state="disabled")

import tkinter as tkimport tkinter.ttk as ttkimport tracebackclass MyApp(tk.Tk):    def __init__(self):        super().__init__()        tk.Button(self, text='test error', command=self.run_bad_math).pack()    @staticmethod    def run_bad_math():        try:            1/0        except Exception as error:            title = 'Traceback Error'            message = "An error has occurred: '{}'.".format(error)            detail = traceback.format_exc()            TopErrorWindow(title, message, detail)class TopErrorWindow(tk.Toplevel):    def __init__(self, title, message, detail):        tk.Toplevel.__init__(self)        self.details_expanded = False        self.title(title)        self.geometry('350x75')        self.minsize(350, 75)        self.maxsize(425, 250)        self.rowconfigure(0, weight=0)        self.rowconfigure(1, weight=1)        self.columnconfigure(0, weight=1)        button_frame = tk.Frame(self)        button_frame.grid(row=0, column=0, sticky='nsew')        button_frame.columnconfigure(0, weight=1)        button_frame.columnconfigure(1, weight=1)        text_frame = tk.Frame(self)        text_frame.grid(row=1, column=0, padx=(7, 7), pady=(7, 7), sticky='nsew')        text_frame.rowconfigure(0, weight=1)        text_frame.columnconfigure(0, weight=1)        ttk.Label(button_frame, text=message).grid(row=0, column=0, columnspan=2, pady=(7, 7))        ttk.Button(button_frame, text='OK', command=self.destroy).grid(row=1, column=0, sticky='e')        ttk.Button(button_frame, text='Details', command=self.toggle_details).grid(row=1, column=1, sticky='w')        self.textbox = tk.Text(text_frame, height=6)        self.textbox.insert('1.0', detail)        self.textbox.config(state='disabled')        self.scrollb = tk.Scrollbar(text_frame, command=self.textbox.yview)        self.textbox.config(yscrollcommand=self.scrollb.set)    def toggle_details(self):        if self.details_expanded:            self.textbox.grid_forget()            self.scrollb.grid_forget()            self.geometry('350x75')            self.details_expanded = False        else:            self.textbox.grid(row=0, column=0, sticky='nsew')            self.scrollb.grid(row=0, column=1, sticky='nsew')            self.geometry('350x160')            self.details_expanded = Trueif __name__ == '__main__':    App = MyApp().mainloop()

Results:

enter image description here

enter image description here

Now with resizing :D

enter image description here

Update:

In response to your statement below:

The error window will not display if a Tk instance hasn't been initialized first.

If we set up the class as its own Tk() instance it can be used as a stand alone error pop-up. I have also added some alignment changes and some resizing control to make this class a bit more conformative to the standard error messages you mention in the comments.

See below code.

import tkinter as tkimport tkinter.ttk as ttkclass TopErrorWindow(tk.Tk):    def __init__(self, title, message, detail):        super().__init__()        self.details_expanded = False        self.title(title)        self.geometry('350x75')        self.minsize(350, 75)        self.maxsize(425, 250)        self.resizable(False, False)        self.rowconfigure(0, weight=0)        self.rowconfigure(1, weight=1)        self.columnconfigure(0, weight=1)        button_frame = tk.Frame(self)        button_frame.grid(row=0, column=0, sticky='nsew')        button_frame.columnconfigure(0, weight=1)        button_frame.columnconfigure(1, weight=1)        text_frame = tk.Frame(self)        text_frame.grid(row=1, column=0, padx=(7, 7), pady=(7, 7), sticky='nsew')        text_frame.rowconfigure(0, weight=1)        text_frame.columnconfigure(0, weight=1)        ttk.Label(button_frame, text=message).grid(row=0, column=0, columnspan=3, pady=(7, 7), padx=(7, 7), sticky='w')        ttk.Button(button_frame, text='OK', command=self.destroy).grid(row=1, column=1, sticky='e')        ttk.Button(button_frame, text='Details',                   command=self.toggle_details).grid(row=1, column=2, padx=(7, 7), sticky='e')        self.textbox = tk.Text(text_frame, height=6)        self.textbox.insert('1.0', detail)        self.textbox.config(state='disabled')        self.scrollb = tk.Scrollbar(text_frame, command=self.textbox.yview)        self.textbox.config(yscrollcommand=self.scrollb.set)        self.mainloop()    def toggle_details(self):        if self.details_expanded:            self.textbox.grid_forget()            self.scrollb.grid_forget()            self.resizable(False, False)            self.geometry('350x75')            self.details_expanded = False        else:            self.textbox.grid(row=0, column=0, sticky='nsew')            self.scrollb.grid(row=0, column=1, sticky='nsew')            self.resizable(True, True)            self.geometry('350x160')            self.details_expanded = True

Results:

enter image description here

enter image description here

You can add an image as well using canvas with the type of error image you want.