[UG 二次开发 PYTHON] 添加螺纹规格
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] 添加螺纹规格的更多相关文章
- Openstack Murano(kilo)二次开发之添加Volume
Openstack Murano(kilo)二次开发之添加Volume 欢迎转载,转载请注明出处:http://www.cnblogs.com/fmnisme/p/openstack_murano_a ...
- TFS二次开发系列:四、TFS二次开发WorkItem添加和修改、保存
WorkItemStore:表示跟踪与运行 Team Foundation Server的服务器的工作项客户端连接. A.添加工作项 1.首先获得某服务器的WorkItemStore. WorkIte ...
- 【转】Jenkins 二次开发 - Python
马克,备用: Jenkins 二次开发 https://testerhome.com/topics/14988?locale=zh-TW python-jenkins api 文档:https://p ...
- UG二次开发-CAM-获取修改路径参数
项目中要获取路径参数,网上大多是C++的例子,而本项目是用C#写的,探索了下,记录下. 以获取某条路径的刀具号为例,其他参数依此类推. using System; using System.Colle ...
- phpcms v9 二次开发 - 自己添加源文件
一.在根目录添加入口文件, 我现在要在根目录添加一个文件名为test.php 这样一个文件,为了调用系统的公用类和函数,必须加入一下包含文件 test.php代码如下 <?phpdefine(' ...
- 基于ZFAKA二次开发,添加PayJS支付渠道
项目地址:https://github.com/hiyouli/payjs-for-zfaka 关于ZFAKA,请移步:ZFAKA 免费.安全.稳定.高效的发卡系统,值得拥有! 演示地址:http:/ ...
- Revit二次开发之添加选项卡和按钮
我们日常在revit开发中经常会用到按钮,可以通过revitAPI提供的接口创建按钮,今天我简单介绍一下两种按钮,一种是单命令按钮,另一种是含下拉菜单的按钮,包括创建他们的方法. 实现方法 1.实 ...
- UG二次开发-CAM-执行方式
以C#开发为例,通常先用[操作记录]功能录制关键代码,得到一个.cs文件. (1)可以直接使用[播放操作记录]的方式执行该.cs文件. (2)可以建立一个C#的类库工程,将上述.cs文件加载进去,添加 ...
- Ubuntu环境下Nutch1.2 二次开发(添加中文分词)
前提nutch1.2已部署到eclipse中 详见:http://www.cnblogs.com/cy163/archive/2013/02/19/2916419.html 1 部署IKAnalyze ...
- NX二次开发-自定义添加右键菜单RegisterConfigureContextMenuCallback
首先声明这个知识我以前不知道,是夏天的时候看到别人在唐工的QQ群里问的,唐工说西门子官方有这个例子.那个时候我因为在忙其他事情,也就没去研究那个右键菜单到底是怎么做的.关于自定义添加右键菜单Regis ...
随机推荐
- WPF 纯xaml实现控件运动动画
1.Image控件加载后上下运动 2.Image控件可以放在Grid等布局控件中 3.指定加载时触发动画: EventTrigger RoutedEvent="Image.Loaded&qu ...
- synchronized原理-字节码分析、对象内存结构、锁升级过程、Monitor
本文分析的问题: synchronized 字节码文件分析之 monitorenter.monitorexit 指令 为什么任何一个Java对象都可以成为一把锁? 对象的内存结构 锁升级过程 Moni ...
- 面向K-12学生的远程访问学校计算机实验室
为了应对新冠肺炎大流行,许多学校被迫采用远程学习和混合时间制度.在家学习的学生必须使用自己的个人设备或学校提供的设备(例如 Chromebook )来完成课堂作业. 尽管许多解决方案可以帮助学生和 ...
- 在uGUI正交相机中实现旋转透视效果
正常uGUI使用正交相机的话,旋转是没有透视效果的,但如果能实现较简单的透视, 对一些效果表现来说还是不错的:见下图(左为透视效果): 正常思路感觉各种麻烦. 因为uGUI使用unity的x和y方向表 ...
- 动态类型语言 VS 静态类型语言
一. 运行期动态修改类型结构 动态编程语言是高级编程语言的一个类别,在计算机科学领域已被广泛应用.它是一类在运行时可以改变其结构的语言:例如新的函数.对象.甚至代码可以被引进,已有的函数可以被删除或是 ...
- mysql存储地理信息的方法
MySQL 存储地理信息通常使用 GEOMETRY 数据类型或其子类型(如 POINT, LINESTRING, POLYGON 等).为了支持这些数据类型,MySQL 提供了 SPATIAL 索引, ...
- Flutter学习网站和安装问题
一.Flutter网站 Flutter中文开发者网站(推荐) https://flutter.cn/ 二.Flutter第三方库 Pub.Dev https://pub.dev/ 三.Flutter源 ...
- kubenetes中的pod删除策略 级联删除与非级联删除
StatefulSet 有状态应用[有状态应用] 有状态:StatefulSet - 集群节点之间的关系. - 数据不完全一致. - 实例之间不对等的关系. - 依靠外部存储的应用. - 通过dns维 ...
- itest(爱测试) 紧急 BUG 修复版(4.5.6)发布,,开源BUG 跟踪管理 & 敏捷测试管理&极简项目管理软件
itest 简介 itest 开源敏捷测试管理,testOps 践行者,极简的任务管理,测试管理,缺陷管理,测试环境管理4合1,又有丰富的统计分析.可按测试包分配测试用例执行,也可建测试迭代(含任务, ...
- 01-布局扩展-用calc来计算实现双飞翼布局
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8 ...