如何在tkinter消息框中添加“显示详情”按钮?

11

我有一个使用tkinter.messagebox的Python脚本,如果发生意外异常,它会显示带有回溯细节的错误消息。

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())

Standard tkinter error

以这种方式显示跟踪记录有一些缺点。

与其默认显示错误详细信息,我想添加一个“显示详细信息”按钮,该按钮将在只读文本字段中显示更多信息。

Detailed error for "division by zero"

我该如何在tkinter中的messagebox中添加“显示详情”按钮?

3
дҪ еҸҜд»ҘеҲӣе»әиҮӘе·ұзҡ„зұ»дјјдәҺmessageboxзҡ„еҜ№иҜқжЎҶзӘ—еҸЈгҖӮиҝҷйҮҢжңүдёҖд»Ҫз®ҖиҰҒж–ҮжЎЈпјҢиҜ·жіЁж„Ҹзү№еҲ«е…іжіЁ tkSimpleDialog.py ж”ҜжҢҒзұ»гҖӮ - martineau
我会使用 Toplevel() 来创建自己的窗口。 - Mike - SMT
1个回答

12

我会使用Toplevel()窗口构建自己的客户错误框。

我认为在这里使用ttk按钮是一个不错的想法,并且通过框架和权重的组合,我们可以让窗口看起来足够好。

为了防止用户调整窗口大小,我还设置了一种方法来切换详细信息文本框。通过跟踪变量和if / else语句的使用,很容易设置。

最后,我们可以使用.config(state =“disabled”)禁用文本框。

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


class 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 = True


if __name__ == '__main__':
    App = MyApp().mainloop()

结果:

enter image description here

enter image description here

现在可以进行调整大小:D

enter image description here

更新:

针对您下面的声明:

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

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

请参见下面的代码。

import tkinter as tk
import tkinter.ttk as ttk


class 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

结果:

enter image description here

enter image description here

你也可以使用画布添加错误类型的图片。


让我们在聊天中继续这个讨论 - Stevoisiak
你的答案很好用。我计划在宽限期内授予你赏金。 - Stevoisiak
@StevenVascellaro 啊,我不知道有宽限期。看来阅读整个赏金页面是有帮助的 :D - Mike - SMT
需要注意的几点:1)如果没有先初始化Tk实例,则错误窗口不会显示。2)消息提示通常将文本和按钮对齐到左侧或右侧,而不是居中。3)“Traceback Error”拼写错误为“Teackback Error”。 - Stevoisiak
在大多数操作系统中,消息提示通常将消息左对齐,将按钮右对齐。(WindowsMacLinux - Stevoisiak
@StevenVascellaro 我已经添加了一个独立的示例,应该可以解决您在上面评论中提到的所有问题。如果我漏掉了什么,请告诉我。 - Mike - SMT

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接