ttkbootstrap的Messagebox在多线程函数中无法使用,如何解决?

背景:我用自带tk界面写了个程序,后面觉得太丑就换ttkbootstrap试试,但是在修改程序过程中发现消息框始终无法在def中正常运行。求帮忙看看咋回事。

这是tk的代码,关闭程序正常弹消息框。

import sys
import threading
import tkinter as tk
from tkinter import messagebox
from tkinter.messagebox import askyesno


class TestGui:
    def __init__(self, init_window_name):
        self.init_window_name = init_window_name
        self.init_window_name.title("555")
        self.init_window_name.geometry("310x380")
        self.init_window_name.protocol('WM_DELETE_WINDOW', lambda: self.thread_it(self.clos_window))

    def thread_it(self, func, *args):
        """ 将函数打包进线程 """
        self.myThread = threading.Thread(target=func, args=args)
        self.myThread .setDaemon(True)  # 主线程退出就直接让子线程跟随退出,不论是否运行完成。
        self.myThread .start()


    def clos_window(self):
        ans = askyesno(title='通知', message='是否退出程序')
        if ans:
            self.init_window_name.destroy()
            sys.exit()
        else:
            return None

if __name__ == '__main__':
    init_window = tk.Tk()
    init_window.attributes("-topmost", 1)
    test_gui = TestGui(init_window)
    init_window.mainloop()




这个是换ttk后改的代码 消息框始终无法正常运行,弹窗之前的555是能打印出来的。报了这个错误:RuntimeError: Calling Tcl from different apartment



import ttkbootstrap as ttk
from ttkbootstrap.dialogs import Messagebox
import threading

class TestGui:
    def __init__(self, root_window):
        self.root_windows = root_window
        self.root_windows.title("11111111")
        self.root_windows.geometry("380x285")
        self.root_windows.protocol('WM_DELETE_WINDOW', lambda: self.thread_it(self.clos_window))
        self.Messgebox = Messagebox


    def clos_window(self):
        print("555")
        self.Messgebox.show_warning(message="显示警告")

    def thread_it(self, func, *args):
        self.myThread = threading.Thread(target=func, args=args)
        self.myThread .setDaemon(True)
        self.myThread .start()

if __name__ == '__main__':
    root_window = ttk.Window()
    root_window.attributes("-topmost", 1)
    root_window.resizable(width=False, height=False)
    test_gui = TestGui(root_window)
    root_window.mainloop()


起初以为没执行函数 后面加了打印发现正常执行的,唯独这个消息框报错,不清楚是线程原因还是我写的不对。我试过添加按钮去执行def 也是报错。但我在原来的tk程序里边用就没问题。

回答不易,求求您点赞采纳哦

看起来您正在尝试在多线程函数中使用Messagebox该类,但遇到运行时错误“从不同的单元调用 Tcl”。ttkbootstrap此错误通常是由于尝试从非主线程的线程调用 Tkinter 函数引起的。

要解决此问题,您需要确保对 Tkinter 函数的任何调用都是从主线程进行的。一种方法是使用after主窗口的方法来安排稍后在主线程中进行的函数调用。

例如,您可以修改clos_window函数如下:

def clos_window(self):
    print("555")
    self.root_windows.after(0, self.Messgebox.show_warning, message="显示警告")

这将安排show_warning方法在延迟 0 毫秒后在主线程中调用。

或者,您可以使用 aQueue在主线程和工作线程之间传递消息,并让主线程通过调用适当的 Tkinter 函数来处理消息。