使用FreeCAD Python宏时,弹出QDialog子窗口为何会暂停脚本?
FreeCAD宏中模态对话框阻塞脚本执行的问题原因与解决方案
问题原因
触发Path_Job按钮后弹出的Project Setup对话框是模态QDialog。模态对话框的核心特性是会阻塞当前执行线程的事件循环,直到用户手动关闭对话框才会继续执行后续代码。这就导致你的find_and_click_ok_button()函数根本没有机会运行——脚本被卡在对话框弹出的步骤,直到手动关闭窗口才会走到后续逻辑。
解决方案
方案1:用Qt定时器绕过阻塞
通过QTimer.singleShot将点击OK按钮的逻辑加入Qt事件队列,让事件循环在处理模态对话框时自动执行该逻辑:
from PySide2 import QtWidgets, QtCore def click_toolbar_button(button_name, toolbar_name): mw = FreeCADGui.getMainWindow() # 定位目标工具栏 toolbar = None for tb in mw.findChildren(QtWidgets.QToolBar): if toolbar_name in tb.objectName(): toolbar = tb break if not toolbar: print("未找到目标工具栏") return # 定位目标按钮 target_action = None for action in toolbar.actions(): if action.objectName() == button_name: target_action = action break if not target_action: print(f"未找到按钮:{button_name}") return # 提前设置定时器,延迟100ms执行OK按钮点击(可根据实际调整延迟时间) QtCore.QTimer.singleShot(100, find_and_click_ok_button) # 触发工具栏按钮 target_action.trigger() def find_and_click_ok_button(): print("尝试查找并点击OK按钮") for subwindow in FreeCADGui.getMainWindow().findChildren(QtWidgets.QDialog): if "Project Setup" in subwindow.windowTitle(): ok_button = subwindow.findChild(QtWidgets.QPushButton, "okButton") if ok_button: ok_button.click() print("OK按钮已点击") break click_toolbar_button("Path_Job", "Project Setup")
原理:QTimer.singleShot会把点击逻辑放入Qt的事件队列,当模态对话框弹出并阻塞线程时,Qt的事件循环仍会处理队列中的定时器任务,从而自动完成按钮点击。
方案2:直接调用FreeCAD API(推荐)
模拟GUI点击的方式依赖界面元素,稳定性差。更可靠的方式是直接调用Path工作台的底层API创建Job,完全绕过对话框:
import FreeCAD import Path # 获取当前激活文档,无则新建 doc = FreeCAD.ActiveDocument or FreeCAD.newDocument() # 创建Job对象 job = doc.addObject("Path::Job", "Job") # 设置默认加工控制器(可根据需求替换为其他控制器) job.Controller = Path.Preferences.defaultController() # 可选:绑定加工模型(替换为你的零件对象名称) # job.Model = [doc.getObject("Part")] # 刷新文档 doc.recompute()
这种方式直接操作FreeCAD的数据模型,不依赖GUI元素,避免了界面阻塞问题,是自动化脚本的最优选择。
对话框截图

内容的提问来源于stack exchange,提问作者Josh R
相关产品推荐
相关产品推荐

