-Thomas杨- 2023-01-09 16:35 采纳率: 50%
浏览 65

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程序里边用就没问题。

  • 写回答

1条回答 默认 最新

  • 快撑死的鱼 2023-01-09 18:29
    关注

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

    看起来您正在尝试在多线程函数中使用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 函数来处理消息。

    评论 编辑记录

报告相同问题?

问题事件

  • 创建了问题 1月9日

悬赏问题

  • ¥15 angular项目错误
  • ¥20 需要帮我远程操控一下,运行一下我的那个代码,我觉得我无能为力了
  • ¥20 有偿:在ubuntu上安装arduino以及其常用库文件。
  • ¥15 请问用arcgis处理一些数据和图形,通常里面有一个根据点划泰森多边形的命令,直接划的弊端是只能执行一个完整的边界,但是我们有时候会用到需要在有很多边界内利用点来执行划泰森多边形的命令
  • ¥30 在wave2foam中执行setWaveField时遇到了如下的浮点异常问题,请问该如何解决呢?
  • ¥750 关于一道数论方面的问题,求解答!(关键词-数学方法)
  • ¥200 csgo2的viewmatrix值是否还有别的获取方式
  • ¥15 Stable Diffusion,用Ebsynth utility在视频选帧图重绘,第一步报错,蒙版和帧图没法生成,怎么处理啊
  • ¥15 请把下列每一行代码完整地读懂并注释出来
  • ¥15 寻找公式识别开发,自动识别整页文档、图像公式的软件