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

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

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

效果图

上代码

  1. # nx: threaded
  2. from typing import List
  3. import os
  4. from bs4 import BeautifulSoup as bs
  5. import bs4
  6. from PySide6 import QtCore as qc
  7. from PySide6 import QtWidgets as qw
  8. from PySide6 import QtGui as qg
  9. os.chdir(os.path.dirname(os.path.abspath(__file__)))
  10. r_path = ""
  11. w_path = ""
  12. class mw(qw.QDialog):
  13. def __init__(self) -> None:
  14. super().__init__()
  15. self.ly_main = qw.QHBoxLayout(self)
  16. """主框架"""
  17. self.ly_left = qw.QHBoxLayout()
  18. """左 主 框架"""
  19. self.ly_left_up = qw.QVBoxLayout()
  20. """左 上 框架"""
  21. self.ly_left_down = qw.QVBoxLayout()
  22. """左 下 框架"""
  23. self.ly_mid = qw.QVBoxLayout()
  24. """中 主 框架"""
  25. self.ly_right = qw.QVBoxLayout()
  26. """右 主 框架"""
  27. self.ly_left_down.addLayout(self.ly_left_up, 0)
  28. self.ly_left_down.addLayout(self.ly_left, 1)
  29. self.lb_show = qw.QLabel("start")
  30. self.ly_left_up.addWidget(self.lb_show, 1)
  31. self.static_lb_1 = qw.QLabel("Unit")
  32. self.cb_unit = qw.QComboBox(self)
  33. self.cb_unit.addItems(["Metric", "Inch"])
  34. self.cb_unit.currentIndexChanged.connect(self.on_cb_unit_change)
  35. self.ly_left_up.addWidget(self.static_lb_1, 1)
  36. self.ly_left_up.addWidget(self.cb_unit, 1)
  37. self.static_lb_2 = qw.QLabel("Standard")
  38. self.cb_standard = qw.QComboBox(self)
  39. self.cb_standard.currentIndexChanged.connect(self.on_cb_standard_change)
  40. self.ly_left_up.addWidget(self.static_lb_2, 1)
  41. self.ly_left_up.addWidget(self.cb_standard, 1)
  42. self.static_lb_3 = qw.QLabel("Size")
  43. self.cb_size = qw.QComboBox(self)
  44. self.cb_size.currentIndexChanged.connect(self.on_cb_size_change)
  45. self.ly_left_up.addWidget(self.static_lb_3, 1)
  46. self.ly_left_up.addWidget(self.cb_size, 1)
  47. self.lb_show_name = qw.QLabel("")
  48. self.ly_left_up.addWidget(self.lb_show_name, 1)
  49. self.mm = qw.QLineEdit()
  50. self.pp = qw.QLineEdit()
  51. self.bt_copy = qw.QPushButton("复制")
  52. self.bt_insert = qw.QPushButton("插入")
  53. self.bt_save = qw.QPushButton("保存")
  54. self.bt_edit = qw.QPushButton("修改")
  55. self.bt_copy.clicked.connect(self.on_bt_copy_click)
  56. self.bt_insert.clicked.connect(self.on_bt_insert_click)
  57. self.bt_save.clicked.connect(self.on_bt_save_click)
  58. self.bt_edit.clicked.connect(self.on_bt_edit_click)
  59. self.ly_left_up.addWidget(self.bt_copy)
  60. self.ly_left_up.addWidget(qw.QLabel("螺径"))
  61. self.ly_left_up.addWidget(self.mm)
  62. self.ly_left_up.addWidget(qw.QLabel("螺距"))
  63. self.ly_left_up.addWidget(self.pp)
  64. self.ly_left_up.addWidget(self.bt_edit)
  65. self.ly_left_up.addWidget(self.bt_insert)
  66. self.ly_left_up.addWidget(self.bt_save)
  67. self.tb_mid = qw.QTableWidget(40, 2, self)
  68. self.tb_mid.setHorizontalHeaderLabels(["属性", "值"])
  69. self.ly_mid.addWidget(qw.QLabel("原始数据"))
  70. self.ly_mid.addWidget(self.tb_mid)
  71. self.tb_right = qw.QTableWidget(40, 2, self)
  72. self.tb_right.setHorizontalHeaderLabels(["属性", "值"])
  73. self.ly_right.addWidget(qw.QLabel("修改数据"))
  74. self.ly_right.addWidget(self.tb_right)
  75. self.scrollbar_mid = self.tb_mid.verticalScrollBar()
  76. self.scrollbar_right = self.tb_right.verticalScrollBar()
  77. self.scrollbar_mid.valueChanged.connect(self.on_tb_mid_scroll)
  78. self.scrollbar_right.valueChanged.connect(self.on_tb_right_scroll)
  79. self.setLayout(self.ly_main)
  80. self.ly_main.addLayout(self.ly_left_down)
  81. self.ly_main.addLayout(self.ly_mid)
  82. self.ly_main.addLayout(self.ly_right)
  83. self.resize(900, 600)
  84. x = thread_xml_reader()
  85. r = x.read_xml(r_path)
  86. rot = next(r.children)
  87. nds2 = []
  88. for i in rot.children:
  89. if isinstance(i, bs4.element.NavigableString) and len(str(i).strip()) == 0:
  90. pass
  91. else:
  92. nds2.append(i)
  93. self.rt = hole_root(nds2)
  94. self.tgs: List[bs4.element.Tag] = []
  95. self.crt = 0
  96. self.cb_size_lst = []
  97. self._crt_unit = ""
  98. self._crt_standard = ""
  99. self.crt_unit = "Metric"
  100. self.crt_data: bs4.element.Tag = None
  101. self.copyed_tg: bs4.element.Tag = None
  102. self.crt = 0
  103. @property
  104. def crt(self):
  105. """当前序号"""
  106. return self._crt
  107. @crt.setter
  108. def crt(self, value):
  109. self._crt = value
  110. if self._crt < 0:
  111. self.lb_show_name.setText("start")
  112. elif self._crt >= len(self.tgs):
  113. self.lb_show_name.setText("over")
  114. else:
  115. self.lb_show_name.setText(f"current: {self._crt}, next =>")
  116. self.cb_size.setCurrentIndex(self._crt)
  117. if self._crt >= len(self.tgs):
  118. self.tb_mid.clearContents()
  119. self.lb_show_name.setText("")
  120. self.lb_show.setText("over")
  121. else:
  122. tg = self.tgs[self._crt]
  123. attrs = tg.attrs
  124. self.lb_show_name.setText(tg.name)
  125. self.lb_show.setText(f"当前 {self._crt} next->")
  126. i = 0
  127. for k, v in attrs.items():
  128. item = qw.QTableWidgetItem(str(k))
  129. self.tb_mid.setItem(i, 0, item)
  130. item = qw.QTableWidgetItem(f"{str(v)}")
  131. self.tb_mid.setItem(i, 1, item)
  132. i += 1
  133. self.crt_data = tg
  134. @property
  135. def crt_unit(self) -> str:
  136. """当前的系列 Metric Inch"""
  137. return self._crt_unit
  138. @crt_unit.setter
  139. def crt_unit(self, value):
  140. if value == self._crt_unit:
  141. pass
  142. else:
  143. self._crt_unit = value
  144. self.cb_standard.clear()
  145. if value == "Metric":
  146. rr = self.rt.metric
  147. elif value == "Inch":
  148. rr = self.rt.inch
  149. else:
  150. return
  151. self.cb_size_lst = rr.ssnames
  152. self.cb_standard.addItems(rr.ssnames)
  153. @property
  154. def crt_standard(self):
  155. """当前标号"""
  156. return self._crt_standard
  157. @crt_standard.setter
  158. def crt_standard(self, value):
  159. if value == self._crt_standard:
  160. pass
  161. else:
  162. self._crt_standard = value
  163. vv = self.cb_unit.currentText()
  164. if vv == "Metric":
  165. rr = self.rt.metric
  166. elif vv == "Inch":
  167. rr = self.rt.inch
  168. vvs = self.cb_standard.currentText()
  169. if vvs == "":
  170. vvs = self.cb_size_lst[0]
  171. r3: hole_standard = None
  172. for i in rr.ss:
  173. if i.standard == vvs:
  174. r3 = i
  175. break
  176. if r3 != None:
  177. self.tgs = r3.holes
  178. xx = [i.attrs["Size"] for i in self.tgs]
  179. self.cb_size.clear()
  180. self.cb_size.addItems(xx)
  181. self.crt = 0
  182. def on_cb_unit_change(self):
  183. self.crt_unit = self.cb_unit.currentText()
  184. def on_cb_standard_change(self):
  185. self.crt_standard = self.cb_standard.currentText()
  186. def on_cb_size_change(self):
  187. idx = self.cb_size.currentIndex()
  188. if idx != self._crt:
  189. self.crt = idx
  190. def on_bt_copy_click(self) -> None:
  191. attrs = self.crt_data.attrs.copy()
  192. attrs["Standard"] = "User"
  193. self.copyed_tg = bs4.element.Tag(
  194. attrs=attrs, name=self.crt_data.name, can_be_empty_element=True
  195. )
  196. attrs = self.copyed_tg.attrs
  197. self.toTb3()
  198. def on_bt_insert_click(self) -> None:
  199. ss = self.rt.metric.user.hole_sizes
  200. if self.copyed_tg is None:
  201. return
  202. else:
  203. tg_size = self.copyed_tg.attrs["Size"]
  204. if tg_size not in ss:
  205. self.rt.metric.user.holes.append(self.copyed_tg)
  206. self.rt.metric.user.holes.sort(
  207. key=lambda x: float(x.attrs["Size"][1:].split(" ")[0])
  208. )
  209. ss = self.rt.metric.user.hole_sizes
  210. ct = -1
  211. for i in range(len(ss)):
  212. if ss[i] == tg_size:
  213. ct = i
  214. break
  215. self.cb_unit.setCurrentText("Metric")
  216. self.cb_standard.setCurrentText("User")
  217. self.crt = ct
  218. def on_bt_save_click(self) -> None:
  219. if w_path != "":
  220. with open(w_path, "w") as f:
  221. for i in self.rt.toStr():
  222. f.write(i)
  223. def toTb3(self):
  224. """更新表3"""
  225. if self.copyed_tg is not None:
  226. attrs = self.copyed_tg.attrs
  227. i = 0
  228. for k, v in attrs.items():
  229. item1 = qw.QTableWidgetItem(str(k))
  230. self.tb_right.setItem(i, 0, item1)
  231. item2 = qw.QTableWidgetItem(f"{str(v)}")
  232. self.tb_right.setItem(i, 1, item2)
  233. i += 1
  234. if k == "Standard":
  235. item2.setFlags(item2.flags() ^ qc.Qt.ItemIsEditable)
  236. def on_bt_edit_click(self) -> None:
  237. mmm = 0
  238. ppp = 0
  239. if self.copyed_tg is None:
  240. return
  241. tt = self.tb_right.item(1, 1).text()
  242. if tt != "Metric":
  243. return
  244. try:
  245. mmm = int(self.mm.text())
  246. ppp = round(float(self.pp.text()), 2)
  247. except:
  248. pass
  249. if mmm <= 0 or ppp <= 0:
  250. return
  251. self.copyed_tg.attrs["Size"] = f"M{mmm} x {ppp}"
  252. self.copyed_tg.attrs["ScrewSize"] = f"M{mmm}"
  253. self.copyed_tg.attrs["MajorDiameter"] = f"{mmm}"
  254. self.copyed_tg.attrs["MinorDiameter"] = f"{round(mmm-ppp,3)}"
  255. self.copyed_tg.attrs["TapDrillDia"] = f"{round(mmm-ppp+0.01,1)}"
  256. self.copyed_tg.attrs["ShaftDiameter"] = f"{mmm}"
  257. self.copyed_tg.attrs["Pitch"] = f"{ppp}"
  258. self.copyed_tg.attrs["Callout"] = f"M{mmm}_x_{ppp}"
  259. self.copyed_tg.attrs["HoleDepth"] = f"{mmm*2}"
  260. self.copyed_tg.attrs["ThreadDepth"] = f"{int(mmm*1.5)}"
  261. self.copyed_tg.attrs["ReliefDiameter"] = f"{float(mmm):0.3f}"
  262. self.copyed_tg.attrs["ReliefDepth"] = f"{mmm*0.5:0.3f}"
  263. self.copyed_tg.attrs["ReliefChamferOffset"] = f"{round(ppp*1.1,1):0.3f}"
  264. self.copyed_tg.attrs["StartChamferDiameter"] = f"{float(mmm):0.3f}"
  265. self.copyed_tg.attrs["EndChamferDiameter"] = f"{float(mmm):0.3f}"
  266. self.toTb3()
  267. def on_tb_mid_scroll(self, e):
  268. self.tb_right.verticalScrollBar().setValue(e)
  269. def on_tb_right_scroll(self, e):
  270. self.tb_mid.verticalScrollBar().setValue(e)
  271. class thread_xml_reader:
  272. def __init__(self) -> None:
  273. pass
  274. def read_xml(self, rpath: str):
  275. if os.path.exists(rpath):
  276. with open(rpath, "r", encoding="utf8") as f:
  277. soup = bs(f, "lxml-xml")
  278. return soup
  279. class hole_root:
  280. def __init__(self, hs: List[bs4.element.Tag]) -> None:
  281. met = []
  282. icht = []
  283. for i in hs:
  284. if i.attrs["Unit"] == "Metric":
  285. met.append(i)
  286. elif i.attrs["Unit"] == "Inch":
  287. icht.append(i)
  288. self.metric = hole_metric(met)
  289. self.inch = hole_inch(icht)
  290. def toStr(self):
  291. yield """<?xml version="1.0" encoding="UTF-8" standalone="yes"?>\n"""
  292. #yield "<root>\n"
  293. yield "<Root>\n"
  294. for i in self.inch.ss:
  295. for k in i.holes:
  296. kas = k.attrs
  297. r = " <" + k.name
  298. for k, v in kas.items():
  299. r += f' {k}="{v}"'
  300. r += " />\n"
  301. yield r
  302. for i in self.metric.ss:
  303. for k in i.holes:
  304. kas = k.attrs
  305. r = " <" + k.name
  306. for k, v in kas.items():
  307. r += f' {k}="{v}"'
  308. r += " />\n"
  309. yield r
  310. #yield "</root>"
  311. yield "</Root>"
  312. class hole_metric:
  313. """Metric"""
  314. unit = "Metric"
  315. def __init__(self, hs: List[bs4.element.Tag]) -> None:
  316. rr = {}
  317. nn = []
  318. for i in hs:
  319. s = i.attrs["Standard"]
  320. if s in nn:
  321. rr[s].append(i)
  322. else:
  323. nn.append(s)
  324. rr[s] = [i]
  325. self.ss: List[hole_standard] = [hole_standard(k, v) for k, v in rr.items()]
  326. for i in self.ss:
  327. if i.standard == "User":
  328. self.user = i
  329. break
  330. else:
  331. self.user = hole_standard("User", [])
  332. self.ss.append(self.user)
  333. @property
  334. def ssnames(self):
  335. return [i.standard for i in self.ss]
  336. class hole_inch:
  337. """Inch"""
  338. unit = "Inch"
  339. def __init__(self, hs: List[bs4.element.Tag]) -> None:
  340. rr = {}
  341. nn = []
  342. for i in hs:
  343. s = i.attrs["Standard"]
  344. if s in nn:
  345. rr[s].append(i)
  346. else:
  347. nn.append(s)
  348. rr[s] = [i]
  349. self.ss = [hole_standard(k, v) for k, v in rr.items()]
  350. @property
  351. def ssnames(self):
  352. return [i.standard for i in self.ss]
  353. class hole_standard:
  354. "standard"
  355. def __init__(self, name: str, hs: List[bs4.element.Tag]) -> None:
  356. self.standard = name
  357. self.holes = hs
  358. @property
  359. def hole_sizes(self) -> List[str]:
  360. return [i.attrs["Size"] for i in self.holes]
  361. def main():
  362. app = qw.QApplication()
  363. mm = mw()
  364. mm.show()
  365. app.exec()
  366. exit()
  367. if __name__ == "__main__":
  368. ug_base_dir = os.getenv("UGII_BASE_DIR")
  369. if ug_base_dir is None or ug_base_dir == "":
  370. pass
  371. else:
  372. file_dir = os.path.join(ug_base_dir, "UGII", "modeling_standards")
  373. w_path = r_path = os.path.join(file_dir, "NX_Thread_Standard.xml")
  374. backup_path = os.path.join(file_dir, "NX_Thread_Standard_bak.xml")
  375. if not os.path.exists(r_path):
  376. raise FileNotFoundError(r_path)
  377. if not os.path.exists(backup_path):
  378. import shutil
  379. shutil.copy(r_path, backup_path)
  380. 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. jeecg-boot中导出excel冲突问题

    jeecg-boot自带的库是autopoi,如果自定义导出excel引入poi,则需要POI版本要保持一致,否则会出现冲突的情况,导致这2个都用不了的情况. Autopoi底层用的是POI库,poi ...

  2. 密码学—Kasiski测试法Python程序

    Kasiski Kasiski是辅助破解Vigenere的前提工作,Kasiski是猜测加密者使用Vigenere密码体系的密钥的长度,Kasiski只是猜测长度而已,所以说是辅助破解Vigenere ...

  3. docker镜像仓库管理Harbor

    一 部署Harbor 前提: Harbor需要运行在docker上面,所以首先需要在harbor部署机器上面自行部署docker和docker-compose docker-compose安装命令如下 ...

  4. 使用interface化解一场因操作系统不同导致的编译问题

    场景描述 起因: 因项目需求,需要编写一个agent, 需支持Linux和Windows操作系统. Agent里面有一个功能需要获取到服务器上所有已经被占用的端口. 实现方式:针对不同的操作系统,实现 ...

  5. liunx下redis的哨兵环境搭建

    哨兵简介 一定要有一个概念:哨兵实例也是特殊的Redis实例,也就是哨兵实例是独立的进程,多个哨兵实例可以搭建主从(Master-Slave),它们承担的职责和普通的Redis实例不一样.下面是官方文 ...

  6. RocketMQ主从同步原理

    一. 主从同步概述 主从同步这个概念相信大家在平时的工作中,多少都会听到.其目的主要是用于做一备份类操作,以及一些读写分离场景.比如我们常用的关系型数据库mysql,就有主从同步功能在. 主从同步,就 ...

  7. Python并行运算——threading库详解(持续更新)

    0. 写在前面:进程和线程 博文参考: Python的并行(持续更新)_python 并行-CSDN博客 <Python并行编程 中文版> 一些相关概念请见上一篇博文. 1. 在Pytho ...

  8. foxy与galactic解析rosbag的不同之处

    前言 foxy和galactic版本在rosbag2_storage这个包的调整有点大(头文件及接口的命名空间),下面的代码仅供参考使用 foxy #include "db3_reader. ...

  9. LeetCode 680. Valid Palindrome II 验证回文字符串 Ⅱ(C++/Java)

    题目: Given a non-empty string s, you may delete at most one character. Judge whether you can make it ...

  10. C#.NET BC BouncyCastle 国密 SM2 解密遇到 Invalid point encoding 77

    C#.NET BC BouncyCastle 国密 SM2 解密遇到 Invalid point encoding 77 参考:https://blog.csdn.net/seeyouagen/art ...