NX 1988 系列 在添加螺纹特征时,不能自定义螺纹规格,

从网上找到的资料上讲,改一个XML文件,在文件中添加自定义的螺纹规格,从而实现需要的效果。

自己写了一个小程序,方便手动添加螺纹规格。

效果图

上代码

# nx: threaded
from typing import List
import os
from bs4 import BeautifulSoup as bs
import bs4 from PySide6 import QtCore as qc
from PySide6 import QtWidgets as qw
from PySide6 import QtGui as qg os.chdir(os.path.dirname(os.path.abspath(__file__)))
r_path = ""
w_path = "" class mw(qw.QDialog):
def __init__(self) -> None:
super().__init__() self.ly_main = qw.QHBoxLayout(self)
"""主框架"""
self.ly_left = qw.QHBoxLayout()
"""左 主 框架"""
self.ly_left_up = qw.QVBoxLayout()
"""左 上 框架"""
self.ly_left_down = qw.QVBoxLayout()
"""左 下 框架"""
self.ly_mid = qw.QVBoxLayout()
"""中 主 框架"""
self.ly_right = qw.QVBoxLayout()
"""右 主 框架""" self.ly_left_down.addLayout(self.ly_left_up, 0)
self.ly_left_down.addLayout(self.ly_left, 1) self.lb_show = qw.QLabel("start")
self.ly_left_up.addWidget(self.lb_show, 1) self.static_lb_1 = qw.QLabel("Unit")
self.cb_unit = qw.QComboBox(self)
self.cb_unit.addItems(["Metric", "Inch"])
self.cb_unit.currentIndexChanged.connect(self.on_cb_unit_change)
self.ly_left_up.addWidget(self.static_lb_1, 1)
self.ly_left_up.addWidget(self.cb_unit, 1) self.static_lb_2 = qw.QLabel("Standard")
self.cb_standard = qw.QComboBox(self)
self.cb_standard.currentIndexChanged.connect(self.on_cb_standard_change)
self.ly_left_up.addWidget(self.static_lb_2, 1)
self.ly_left_up.addWidget(self.cb_standard, 1) self.static_lb_3 = qw.QLabel("Size")
self.cb_size = qw.QComboBox(self)
self.cb_size.currentIndexChanged.connect(self.on_cb_size_change)
self.ly_left_up.addWidget(self.static_lb_3, 1)
self.ly_left_up.addWidget(self.cb_size, 1) self.lb_show_name = qw.QLabel("")
self.ly_left_up.addWidget(self.lb_show_name, 1) self.mm = qw.QLineEdit()
self.pp = qw.QLineEdit()
self.bt_copy = qw.QPushButton("复制")
self.bt_insert = qw.QPushButton("插入")
self.bt_save = qw.QPushButton("保存")
self.bt_edit = qw.QPushButton("修改")
self.bt_copy.clicked.connect(self.on_bt_copy_click)
self.bt_insert.clicked.connect(self.on_bt_insert_click)
self.bt_save.clicked.connect(self.on_bt_save_click)
self.bt_edit.clicked.connect(self.on_bt_edit_click) self.ly_left_up.addWidget(self.bt_copy)
self.ly_left_up.addWidget(qw.QLabel("螺径"))
self.ly_left_up.addWidget(self.mm)
self.ly_left_up.addWidget(qw.QLabel("螺距"))
self.ly_left_up.addWidget(self.pp)
self.ly_left_up.addWidget(self.bt_edit)
self.ly_left_up.addWidget(self.bt_insert)
self.ly_left_up.addWidget(self.bt_save) self.tb_mid = qw.QTableWidget(40, 2, self)
self.tb_mid.setHorizontalHeaderLabels(["属性", "值"])
self.ly_mid.addWidget(qw.QLabel("原始数据"))
self.ly_mid.addWidget(self.tb_mid) self.tb_right = qw.QTableWidget(40, 2, self)
self.tb_right.setHorizontalHeaderLabels(["属性", "值"])
self.ly_right.addWidget(qw.QLabel("修改数据"))
self.ly_right.addWidget(self.tb_right) self.scrollbar_mid = self.tb_mid.verticalScrollBar()
self.scrollbar_right = self.tb_right.verticalScrollBar()
self.scrollbar_mid.valueChanged.connect(self.on_tb_mid_scroll)
self.scrollbar_right.valueChanged.connect(self.on_tb_right_scroll) self.setLayout(self.ly_main)
self.ly_main.addLayout(self.ly_left_down)
self.ly_main.addLayout(self.ly_mid)
self.ly_main.addLayout(self.ly_right)
self.resize(900, 600) x = thread_xml_reader()
r = x.read_xml(r_path)
rot = next(r.children)
nds2 = []
for i in rot.children:
if isinstance(i, bs4.element.NavigableString) and len(str(i).strip()) == 0:
pass
else:
nds2.append(i)
self.rt = hole_root(nds2) self.tgs: List[bs4.element.Tag] = []
self.crt = 0
self.cb_size_lst = []
self._crt_unit = ""
self._crt_standard = ""
self.crt_unit = "Metric"
self.crt_data: bs4.element.Tag = None
self.copyed_tg: bs4.element.Tag = None
self.crt = 0 @property
def crt(self):
"""当前序号"""
return self._crt @crt.setter
def crt(self, value):
self._crt = value
if self._crt < 0:
self.lb_show_name.setText("start")
elif self._crt >= len(self.tgs):
self.lb_show_name.setText("over")
else:
self.lb_show_name.setText(f"current: {self._crt}, next =>")
self.cb_size.setCurrentIndex(self._crt)
if self._crt >= len(self.tgs):
self.tb_mid.clearContents()
self.lb_show_name.setText("")
self.lb_show.setText("over")
else:
tg = self.tgs[self._crt]
attrs = tg.attrs
self.lb_show_name.setText(tg.name)
self.lb_show.setText(f"当前 {self._crt} next->")
i = 0
for k, v in attrs.items():
item = qw.QTableWidgetItem(str(k))
self.tb_mid.setItem(i, 0, item)
item = qw.QTableWidgetItem(f"{str(v)}")
self.tb_mid.setItem(i, 1, item)
i += 1
self.crt_data = tg @property
def crt_unit(self) -> str:
"""当前的系列 Metric Inch"""
return self._crt_unit @crt_unit.setter
def crt_unit(self, value):
if value == self._crt_unit:
pass
else:
self._crt_unit = value
self.cb_standard.clear()
if value == "Metric":
rr = self.rt.metric
elif value == "Inch":
rr = self.rt.inch
else:
return
self.cb_size_lst = rr.ssnames
self.cb_standard.addItems(rr.ssnames) @property
def crt_standard(self):
"""当前标号"""
return self._crt_standard @crt_standard.setter
def crt_standard(self, value):
if value == self._crt_standard:
pass
else:
self._crt_standard = value
vv = self.cb_unit.currentText()
if vv == "Metric":
rr = self.rt.metric
elif vv == "Inch":
rr = self.rt.inch
vvs = self.cb_standard.currentText()
if vvs == "":
vvs = self.cb_size_lst[0]
r3: hole_standard = None
for i in rr.ss:
if i.standard == vvs:
r3 = i
break
if r3 != None:
self.tgs = r3.holes
xx = [i.attrs["Size"] for i in self.tgs]
self.cb_size.clear()
self.cb_size.addItems(xx)
self.crt = 0 def on_cb_unit_change(self):
self.crt_unit = self.cb_unit.currentText() def on_cb_standard_change(self):
self.crt_standard = self.cb_standard.currentText() def on_cb_size_change(self):
idx = self.cb_size.currentIndex()
if idx != self._crt:
self.crt = idx def on_bt_copy_click(self) -> None:
attrs = self.crt_data.attrs.copy()
attrs["Standard"] = "User"
self.copyed_tg = bs4.element.Tag(
attrs=attrs, name=self.crt_data.name, can_be_empty_element=True
)
attrs = self.copyed_tg.attrs
self.toTb3() def on_bt_insert_click(self) -> None:
ss = self.rt.metric.user.hole_sizes
if self.copyed_tg is None:
return
else:
tg_size = self.copyed_tg.attrs["Size"]
if tg_size not in ss: self.rt.metric.user.holes.append(self.copyed_tg)
self.rt.metric.user.holes.sort(
key=lambda x: float(x.attrs["Size"][1:].split(" ")[0])
)
ss = self.rt.metric.user.hole_sizes
ct = -1
for i in range(len(ss)):
if ss[i] == tg_size:
ct = i
break
self.cb_unit.setCurrentText("Metric")
self.cb_standard.setCurrentText("User")
self.crt = ct def on_bt_save_click(self) -> None:
if w_path != "":
with open(w_path, "w") as f:
for i in self.rt.toStr():
f.write(i) def toTb3(self):
"""更新表3"""
if self.copyed_tg is not None:
attrs = self.copyed_tg.attrs
i = 0
for k, v in attrs.items():
item1 = qw.QTableWidgetItem(str(k))
self.tb_right.setItem(i, 0, item1)
item2 = qw.QTableWidgetItem(f"{str(v)}")
self.tb_right.setItem(i, 1, item2)
i += 1
if k == "Standard":
item2.setFlags(item2.flags() ^ qc.Qt.ItemIsEditable) def on_bt_edit_click(self) -> None:
mmm = 0
ppp = 0
if self.copyed_tg is None:
return
tt = self.tb_right.item(1, 1).text()
if tt != "Metric":
return
try:
mmm = int(self.mm.text())
ppp = round(float(self.pp.text()), 2)
except:
pass
if mmm <= 0 or ppp <= 0:
return
self.copyed_tg.attrs["Size"] = f"M{mmm} x {ppp}"
self.copyed_tg.attrs["ScrewSize"] = f"M{mmm}"
self.copyed_tg.attrs["MajorDiameter"] = f"{mmm}"
self.copyed_tg.attrs["MinorDiameter"] = f"{round(mmm-ppp,3)}"
self.copyed_tg.attrs["TapDrillDia"] = f"{round(mmm-ppp+0.01,1)}"
self.copyed_tg.attrs["ShaftDiameter"] = f"{mmm}"
self.copyed_tg.attrs["Pitch"] = f"{ppp}"
self.copyed_tg.attrs["Callout"] = f"M{mmm}_x_{ppp}"
self.copyed_tg.attrs["HoleDepth"] = f"{mmm*2}"
self.copyed_tg.attrs["ThreadDepth"] = f"{int(mmm*1.5)}"
self.copyed_tg.attrs["ReliefDiameter"] = f"{float(mmm):0.3f}"
self.copyed_tg.attrs["ReliefDepth"] = f"{mmm*0.5:0.3f}"
self.copyed_tg.attrs["ReliefChamferOffset"] = f"{round(ppp*1.1,1):0.3f}"
self.copyed_tg.attrs["StartChamferDiameter"] = f"{float(mmm):0.3f}"
self.copyed_tg.attrs["EndChamferDiameter"] = f"{float(mmm):0.3f}" self.toTb3() def on_tb_mid_scroll(self, e):
self.tb_right.verticalScrollBar().setValue(e) def on_tb_right_scroll(self, e):
self.tb_mid.verticalScrollBar().setValue(e) class thread_xml_reader:
def __init__(self) -> None:
pass def read_xml(self, rpath: str):
if os.path.exists(rpath):
with open(rpath, "r", encoding="utf8") as f:
soup = bs(f, "lxml-xml")
return soup class hole_root:
def __init__(self, hs: List[bs4.element.Tag]) -> None:
met = []
icht = []
for i in hs:
if i.attrs["Unit"] == "Metric":
met.append(i)
elif i.attrs["Unit"] == "Inch":
icht.append(i)
self.metric = hole_metric(met)
self.inch = hole_inch(icht) def toStr(self):
yield """<?xml version="1.0" encoding="UTF-8" standalone="yes"?>\n"""
#yield "<root>\n"
yield "<Root>\n"
for i in self.inch.ss:
for k in i.holes:
kas = k.attrs
r = " <" + k.name
for k, v in kas.items():
r += f' {k}="{v}"'
r += " />\n"
yield r
for i in self.metric.ss:
for k in i.holes:
kas = k.attrs
r = " <" + k.name
for k, v in kas.items():
r += f' {k}="{v}"'
r += " />\n"
yield r
#yield "</root>"
yield "</Root>" class hole_metric:
"""Metric""" unit = "Metric" def __init__(self, hs: List[bs4.element.Tag]) -> None:
rr = {}
nn = []
for i in hs:
s = i.attrs["Standard"]
if s in nn:
rr[s].append(i)
else:
nn.append(s)
rr[s] = [i]
self.ss: List[hole_standard] = [hole_standard(k, v) for k, v in rr.items()]
for i in self.ss:
if i.standard == "User":
self.user = i
break
else:
self.user = hole_standard("User", [])
self.ss.append(self.user) @property
def ssnames(self):
return [i.standard for i in self.ss] class hole_inch:
"""Inch""" unit = "Inch" def __init__(self, hs: List[bs4.element.Tag]) -> None:
rr = {}
nn = []
for i in hs:
s = i.attrs["Standard"]
if s in nn:
rr[s].append(i)
else:
nn.append(s)
rr[s] = [i]
self.ss = [hole_standard(k, v) for k, v in rr.items()] @property
def ssnames(self):
return [i.standard for i in self.ss] class hole_standard:
"standard" def __init__(self, name: str, hs: List[bs4.element.Tag]) -> None:
self.standard = name
self.holes = hs @property
def hole_sizes(self) -> List[str]:
return [i.attrs["Size"] for i in self.holes] def main():
app = qw.QApplication()
mm = mw() mm.show()
app.exec()
exit() if __name__ == "__main__": ug_base_dir = os.getenv("UGII_BASE_DIR")
if ug_base_dir is None or ug_base_dir == "":
pass
else:
file_dir = os.path.join(ug_base_dir, "UGII", "modeling_standards")
w_path = r_path = os.path.join(file_dir, "NX_Thread_Standard.xml")
backup_path = os.path.join(file_dir, "NX_Thread_Standard_bak.xml") if not os.path.exists(r_path):
raise FileNotFoundError(r_path)
if not os.path.exists(backup_path):
import shutil shutil.copy(r_path, backup_path)
main()

没有写删除的功能,怕不小心误操作,要删除某一个规格的话,自己打开 相应的XML文件,手动删除行就行了


22.06.11

输出时的,root 更正为 Root .... 低级错误

[UG 二次开发 PYTHON] 添加螺纹规格的更多相关文章

  1. Openstack Murano(kilo)二次开发之添加Volume

    Openstack Murano(kilo)二次开发之添加Volume 欢迎转载,转载请注明出处:http://www.cnblogs.com/fmnisme/p/openstack_murano_a ...

  2. TFS二次开发系列:四、TFS二次开发WorkItem添加和修改、保存

    WorkItemStore:表示跟踪与运行 Team Foundation Server的服务器的工作项客户端连接. A.添加工作项 1.首先获得某服务器的WorkItemStore. WorkIte ...

  3. 【转】Jenkins 二次开发 - Python

    马克,备用: Jenkins 二次开发 https://testerhome.com/topics/14988?locale=zh-TW python-jenkins api 文档:https://p ...

  4. UG二次开发-CAM-获取修改路径参数

    项目中要获取路径参数,网上大多是C++的例子,而本项目是用C#写的,探索了下,记录下. 以获取某条路径的刀具号为例,其他参数依此类推. using System; using System.Colle ...

  5. phpcms v9 二次开发 - 自己添加源文件

    一.在根目录添加入口文件, 我现在要在根目录添加一个文件名为test.php 这样一个文件,为了调用系统的公用类和函数,必须加入一下包含文件 test.php代码如下 <?phpdefine(' ...

  6. 基于ZFAKA二次开发,添加PayJS支付渠道

    项目地址:https://github.com/hiyouli/payjs-for-zfaka 关于ZFAKA,请移步:ZFAKA 免费.安全.稳定.高效的发卡系统,值得拥有! 演示地址:http:/ ...

  7. Revit二次开发之添加选项卡和按钮

      我们日常在revit开发中经常会用到按钮,可以通过revitAPI提供的接口创建按钮,今天我简单介绍一下两种按钮,一种是单命令按钮,另一种是含下拉菜单的按钮,包括创建他们的方法. 实现方法 1.实 ...

  8. UG二次开发-CAM-执行方式

    以C#开发为例,通常先用[操作记录]功能录制关键代码,得到一个.cs文件. (1)可以直接使用[播放操作记录]的方式执行该.cs文件. (2)可以建立一个C#的类库工程,将上述.cs文件加载进去,添加 ...

  9. Ubuntu环境下Nutch1.2 二次开发(添加中文分词)

    前提nutch1.2已部署到eclipse中 详见:http://www.cnblogs.com/cy163/archive/2013/02/19/2916419.html 1 部署IKAnalyze ...

  10. NX二次开发-自定义添加右键菜单RegisterConfigureContextMenuCallback

    首先声明这个知识我以前不知道,是夏天的时候看到别人在唐工的QQ群里问的,唐工说西门子官方有这个例子.那个时候我因为在忙其他事情,也就没去研究那个右键菜单到底是怎么做的.关于自定义添加右键菜单Regis ...

随机推荐

  1. NSThread的start方法内部做了什么?

    下面是NSThread start方法的汇编码: 1 1 1 ;Foundation`-[NSThread start]: 2 2 2 -> 0x7fff2594f47f <+0>: ...

  2. SpringBoot连接redis报错:exception is io.lettuce.core.RedisException: java.io.IOException: 远程主机强迫关闭了一个现有的连接

    一.解决思路 (1).检查redis的配置是否正确 spring redis: host: localhost port: 6379 password: 123456 database: 0 time ...

  3. mac + docker+单击clickhouse+Dbeaver安装全套

    一.保证docker安装成功 看下教程:https://www.runoob.com/docker/macos-docker-install.html 二.启动桌面版docker 三.下载clickh ...

  4. next-route

    在目录结构中,我们精心创建的每一个文件最终都会经过处理,转化为相应的页面路由.然而,值得注意的是,某些特殊文件格式在生成过程中并不会被当作路由路径来处理. app |-auth login page. ...

  5. Python基础篇(基础知识)

    Python语言基础 pyc 文件 执行Python代码时,如果导入了其他的 .py 文件,那么,执行过程中会自动生成一个与其同名的 .pyc 文件,该文件就是Python解释器编译之后产生的字节码. ...

  6. group_concat 和 case when 的坑

    SELECT size,instrument_id, (CASE side WHEN "sell" THEN group_concat(id ORDER BY id) END )a ...

  7. LLVM技术在GaussDB等数据库中的应用

    本文分享自华为云社区<[GaussTech第3期]LLVM技术在GaussDB等数据库中的应用>,作者:GaussDB 数据库. Hi,别急! 让技术触达每一个角落,赋能更多的人,Gaus ...

  8. itestwork(爱测试) 开源一站式接口测试&敏捷测试工作站 9.0.2Rc2发布

    (一)itest 简介 itest work (爱测试)  一站式工作站让测试变得简单.敏捷,"好用.好看,好敏捷" ,是itest wrok 追求的目标.itest work 包 ...

  9. ssh 端口转发实验

    为什么会使用端口转发 端口转发的优点: 安全性:通过隐藏实际服务(在这种情况下是监听在22端口的SSH服务)的真实端口号,增加了一层安全性.攻击者可能不知道真正的服务端口号,因此更难进行有针对性的攻击 ...

  10. 什么是LAMP

    LAMP Lamp是一种互联网开发架构,全称为LAMP Stack(Linux.Apache.MySQL.PHP).它是一种流行的Web开发环境,用于构建动态网站和Web应用程序.LAMP Stack ...