如何在tkinter消息框中添加"显示详细信息"按钮?

Ste*_*ica 10 python tkinter tkmessagebox

我有一个Python脚本,用于tkinter.messagebox在发生意外异常时显示带有回溯详细信息的错误消息.

import tkinter.messagebox as tm
import traceback

try:
    1/0
except Exception as error:
    tm.showerror(title="Error",
                 message="An error has occurred: '" + str(error) + "'.",
                 detail=traceback.format_exc())
Run Code Online (Sandbox Code Playgroud)

标准tkinter错误

以这种方式显示回溯有一些缺点.

我没有默认显示错误详细信息,而是想添加一个"显示详细信息"按钮,该按钮可以在只读文本字段中显示更多信息.

如何在tkinter消息框中添加"显示详细信息"按钮?

Mik*_*SMT 8

我会用一个Toplevel()窗口来构建我自己的客户错误框.

我认为ttk在这里使用按钮会是一个好主意,并且通过框架和重量的组合,我们可以让窗口显得足够好看.

保持窗口不被用户调整大小我还必须设置一种方法来切换详细信息文本框.使用跟踪变量并使用易于设置的if/else语句.

最后,我们可以禁用文本框 .config(state="disabled")

import tkinter as tk
import tkinter.ttk as ttk
import traceback


class MyApp(tk.Frame):
    def __init__(self, master):
        tk.Frame.__init__(self, master)
        tk.Button(self, text="test error", command=self.run_bad_math).pack()

    def run_bad_math(self):
        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 == False:
            self.textbox.grid(row=0, column=0, sticky='nsew')
            self.scrollb.grid(row=0, column=1, sticky='nsew')
            self.geometry("350x160")
            self.details_expanded = True

        else:
            self.textbox.grid_forget()
            self.scrollb.grid_forget()
            self.geometry("350x75")
            self.details_expanded = False


if __name__ == "__main__":
    root = tk.Tk()
    App = MyApp(root).pack()
    root.mainloop()
Run Code Online (Sandbox Code Playgroud)

结果:

在此输入图像描述

在此输入图像描述

现在调整大小:D

在此输入图像描述

更新:

在回应您的声明如下:

如果尚未首先初始化Tk实例,则不会显示错误窗口.

如果我们将类设置为它自己的Tk()实例,它可以用作独立的错误弹出窗口.我还添加了一些对齐更改和一些调整大小控制,以使此类更符合您在注释中提到的标准错误消息.

见下面的代码.

import tkinter as tk
import tkinter.ttk as ttk
import traceback


class topErrorWindow(tk.Tk):
    def __init__(self, title, message, detail):
        tk.Tk.__init__(self)
        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 == False:
            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

        else:
            self.textbox.grid_forget()
            self.scrollb.grid_forget()
            self.resizable(False, False)
            self.geometry("350x75")
            self.details_expanded = False
Run Code Online (Sandbox Code Playgroud)

结果:

在此输入图像描述

在此输入图像描述

您也可以使用带有所需错误图像类型的画布添加图像.