You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用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元素,避免了界面阻塞问题,是自动化脚本的最优选择。

对话框截图

Project Setup模态对话框

内容的提问来源于stack exchange,提问作者Josh R

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.12 05:44:54