[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 ...
随机推荐
- SpringBoot模拟插入1000000万条数据
一.数据库表准备 CREATE TABLE `student` ( `id` bigint NOT NULL COMMENT '用户id', `name` varchar(50) COLLATE ut ...
- 化繁为简|AIRIOT智慧水务信息化建设解决方案
"生产自动化,管理信息化"是现代化水厂建设的目标之一,需要在水质要求.工艺.生产.管理.环境等监测方面达到精细化管理标准,这是一个高度智能化,实现化繁为简智慧进阶的工程.传统水 ...
- Debian中配置NIS:用户账号管理
1.添加指定gid的组 groupadd -g 1001 upload # 添加了一个指定gid为1001的upload用户 2.添加指定uid的用户,并加入到指定组 useradd -u 1001 ...
- 鸿蒙HarmonyOS实战-Stage模型(线程模型)
前言 线程是计算机中的一种执行单元,是操作系统进行调度的最小单位.它是进程中的实际运行单位,每个进程可以包含多个线程.线程可以理解为进程中的一个执行流,它独立运行,拥有独立的栈和寄存器,但共享进程的资 ...
- .net C# System.Text.Json 如何将 string类型的“true”转换为布尔值 解决方案
直接上解决方法的代码 先定义一个转换顺,代码如下: public sealed class AnhBoolConverter : JsonConverter<bool?> { public ...
- iOS性能优化-内存泄漏
一.现象 最近直播助手在iOS11 ReplayKit上面经常出现进程使用内存超过50MB被系统杀掉,并且这种进程被杀掉不会有任何crash log留下来,只能在Console中留下一点消息. 二.使 ...
- [brief]虚拟机安装UbuntuServer
1.下载Ubuntu--Server镜像官网点击 2.Vmware15.x配置 2G /boot 4G swap(一倍或两倍于分配内存量) rest / or /+/home 3.terminal下安 ...
- unaipp 发送验证码倒计时
view代码 <view class="margin-top" @tap="getCheckNum()"> <view class=" ...
- openstack nova 报错
openstack compute service list The server is currently unavailable. Please try again at a later time ...
- kettle从入门到精通 第五十九课 ETL之kettle 邮件发送多个附件,使用正则轻松解决
问题场景: 一个朋友说他用kettle将生成好的多个文件(a.xls和b.xls,文件在data目录下)发送给客户,但是data目录下还有其他的文件,他如果指定data目录发送会把 data目录下面的 ...