点位设置界面增加了状态设置,从数据库加载状态
This commit is contained in:
128
app/model/point_state.py
Normal file
128
app/model/point_state.py
Normal file
@ -0,0 +1,128 @@
|
||||
"""
|
||||
包括一个点位需要的状态:
|
||||
1、点位名称
|
||||
2、速度
|
||||
3、工具id
|
||||
4、工件id
|
||||
5、关节坐标 J1-J6
|
||||
6、运动类型
|
||||
7、平滑时间
|
||||
"""
|
||||
class PointState:
|
||||
VALID_SPEED_RANGE = (0, 100)
|
||||
VALID_TOOL_WORK_ID_RANGE = (0, 14)
|
||||
VALID_JOINT_COUNT = 6
|
||||
VALID_JOINT_RANGE = (-180, 180)
|
||||
VALID_MOTION_TYPES = ["直线", "曲线中间点", "曲线终点", "自由路径"]
|
||||
VALID_BLEND_TIME_RANGE = (0, 500)
|
||||
|
||||
def __init__(self, pos_name, speed, tool_id, work_id, joint_values, motion_type, blend_time):
|
||||
# 数据合法性判断
|
||||
self.pos_name = self._validate_pos_name(pos_name)
|
||||
self.speed = self._validate_speed(speed)
|
||||
self.tool_id = self._validate_tool_work_id(tool_id, "工具ID")
|
||||
self.work_id = self._validate_tool_work_id(work_id, "工件ID")
|
||||
self.joint_values = self._validate_joint_values(joint_values)
|
||||
self.motion_type = self._validate_motion_type(motion_type)
|
||||
self.blend_time = self._validate_blend_time(blend_time)
|
||||
|
||||
def _validate_pos_name(self, pos_name):
|
||||
"""校验点位名称(非空)"""
|
||||
if not isinstance(pos_name, str):
|
||||
raise TypeError("点位名称必须是字符串类型")
|
||||
stripped_name = pos_name.strip()
|
||||
if not stripped_name:
|
||||
raise ValueError("点位名称不能为空或仅包含空格")
|
||||
return stripped_name
|
||||
|
||||
def _validate_speed(self, speed):
|
||||
"""校验速度(0-100范围)"""
|
||||
if not isinstance(speed, (int, float)):
|
||||
raise TypeError(f"速度必须是数字类型,当前类型:{type(speed).__name__}")
|
||||
min_val, max_val = self.VALID_SPEED_RANGE
|
||||
if not (min_val <= speed <= max_val):
|
||||
raise ValueError(f"速度必须在 {min_val}-{max_val} 之间,当前值:{speed}")
|
||||
return speed
|
||||
|
||||
def _validate_tool_work_id(self, value, field_name):
|
||||
"""校验工具ID/工件ID(0-14范围,整数)"""
|
||||
if not isinstance(value, int):
|
||||
raise TypeError(f"{field_name}必须是整数类型,当前类型:{type(value).__name__}")
|
||||
min_val, max_val = self.VALID_TOOL_WORK_ID_RANGE
|
||||
if not (min_val <= value <= max_val):
|
||||
raise ValueError(f"{field_name}必须在 {min_val}-{max_val} 之间,当前值:{value}")
|
||||
return value
|
||||
|
||||
def _validate_joint_values(self, joint_values):
|
||||
"""校验关节值(6个元素,每个在-180~180范围)"""
|
||||
if not isinstance(joint_values, list):
|
||||
raise TypeError(f"关节值必须是列表类型,当前类型:{type(joint_values).__name__}")
|
||||
if len(joint_values) != self.VALID_JOINT_COUNT:
|
||||
raise ValueError(
|
||||
f"关节值必须包含 {self.VALID_JOINT_COUNT} 个元素(J1-J6),"
|
||||
f"当前数量:{len(joint_values)}"
|
||||
)
|
||||
|
||||
# 逐个校验关节值
|
||||
validated_joints = []
|
||||
for i, val in enumerate(joint_values, 1):
|
||||
if not isinstance(val, (int, float)):
|
||||
raise TypeError(f"J{i}关节值必须是数字类型,当前类型:{type(val).__name__}")
|
||||
|
||||
min_val, max_val = self.VALID_JOINT_RANGE
|
||||
if not (min_val <= val <= max_val):
|
||||
raise ValueError(
|
||||
f"J{i}关节值必须在 {min_val}~{max_val} 之间,当前值:{val}"
|
||||
)
|
||||
validated_joints.append(val)
|
||||
|
||||
return validated_joints
|
||||
|
||||
def _validate_motion_type(self, motion_type):
|
||||
"""校验运动类型(必须是预定义的选项)"""
|
||||
if not isinstance(motion_type, str):
|
||||
raise TypeError(f"运动类型必须是字符串类型,当前类型:{type(motion_type).__name__}")
|
||||
if motion_type not in self.VALID_MOTION_TYPES:
|
||||
raise ValueError(
|
||||
f"运动类型必须是以下之一:{self.VALID_MOTION_TYPES},"
|
||||
f"当前值:{motion_type}"
|
||||
)
|
||||
return motion_type
|
||||
|
||||
def _validate_blend_time(self, blend_time):
|
||||
"""校验平滑时间(-1表示停止,否则0-500范围)"""
|
||||
if not isinstance(blend_time, (int, float)):
|
||||
raise TypeError(f"平滑时间必须是数字类型,当前类型:{type(blend_time).__name__}")
|
||||
|
||||
# 停止模式(-1)或正常平滑时间(0-500)
|
||||
if blend_time == -1:
|
||||
return -1
|
||||
|
||||
min_val, max_val = self.VALID_BLEND_TIME_RANGE
|
||||
if not (min_val <= blend_time <= max_val):
|
||||
raise ValueError(
|
||||
f"平滑时间必须是-1(停止)或 {min_val}-{max_val} 之间(毫秒),"
|
||||
f"当前值:{blend_time}"
|
||||
)
|
||||
return blend_time
|
||||
|
||||
def to_dict(self):
|
||||
"""转换为字典,方便序列化或存储"""
|
||||
return {
|
||||
"pos_name": self.pos_name,
|
||||
"speed": self.speed,
|
||||
"tool_id": self.tool_id,
|
||||
"work_id": self.work_id,
|
||||
"joint_values": self.joint_values,
|
||||
"motion_type": self.motion_type,
|
||||
"blend_time": self.blend_time
|
||||
}
|
||||
|
||||
def __str__(self):
|
||||
"""打印调试"""
|
||||
return (
|
||||
f"点位名:{self.pos_name},速度:{self.speed}%\n"
|
||||
f"工具ID: {self.tool_id},工件ID: {self.work_id}\n"
|
||||
f"关节值:{self.joint_values}\n"
|
||||
f"运动类型:{self.motion_type},平滑时间:{self.blend_time}"
|
||||
)
|
||||
@ -1,6 +1,7 @@
|
||||
# coding:utf-8
|
||||
import sys
|
||||
import os
|
||||
import time
|
||||
from PySide6.QtCore import (
|
||||
Qt,
|
||||
QSize,
|
||||
@ -55,6 +56,9 @@ from ..common.style_sheet import StyleSheet
|
||||
|
||||
import sqlite3
|
||||
|
||||
from .mi_an.status_edit_dialog import StatusEditDialog
|
||||
from ..model.point_state import PointState
|
||||
|
||||
|
||||
class CoodFormsInterface(GalleryInterface):
|
||||
"""Cood Forms interface"""
|
||||
@ -155,6 +159,8 @@ class FormDatabase:
|
||||
j4 DOUBLE NOT NULL DEFAULT -9999.0, --关节角度j4(单位:°)
|
||||
j5 DOUBLE NOT NULL DEFAULT -9999.0, --关节角度j5(单位:°)
|
||||
j6 DOUBLE NOT NULL DEFAULT -9999.0, --关节角度j6(单位:°)
|
||||
motion_type VARCHAR(20) NOT NULL DEFAULT '直线', -- 运动类型
|
||||
blend_time INTEGER NOT NULL DEFAULT -1, -- 平滑时间,-1默认停止
|
||||
ext1 DOUBLE, --扩展字段1
|
||||
ext2 INTEGER, --扩展字段2
|
||||
ext3 TEXT, --扩展字段3
|
||||
@ -259,27 +265,139 @@ class FormDatabase:
|
||||
raise exc
|
||||
|
||||
def insert_form_data(self, form_id, data_rows):
|
||||
# 备注: data_rows 中一行的数据 包含 row_index, x, y, z, rx, ry, rz, name, pos_state
|
||||
# pos_state (点位状态, 字典类型) 包含 pos_name,speed, tool_id, work_id, j1-j6, motion_type, blend_time (状态编辑界面设置完成后插入)
|
||||
"""批量插入form_data表"""
|
||||
try:
|
||||
cursor = self.__connect()
|
||||
for row in data_rows:
|
||||
# row格式: [row_idx, x, y, z, rx, ry, rz]
|
||||
cursor.execute(
|
||||
"""INSERT INTO form_data
|
||||
(form_id, row_index, x, y, z, rx, ry, rz, name)
|
||||
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)""",
|
||||
(
|
||||
form_id,
|
||||
row[0],
|
||||
row[1],
|
||||
row[2],
|
||||
row[3],
|
||||
row[4],
|
||||
row[5],
|
||||
row[6],
|
||||
row[7],
|
||||
),
|
||||
)
|
||||
# row格式: [row_idx, x, y, z, rx, ry, rz, name, pos_state_dict]
|
||||
|
||||
"""
|
||||
row索引为8的列为 点位状态的字典 (pos_state为字典类型)
|
||||
格式如:
|
||||
{'pos_name': 'normal', 'speed': 20.0, 'tool_id': 0, 'work_id': 0,
|
||||
'joint_values': [95.261, 82.247, -180.0, -75.121, -84.143, -15.421],
|
||||
'motion_type': '直线', 'blend_time': -1}
|
||||
"""
|
||||
pos_state_dict = row[8]
|
||||
|
||||
if not pos_state_dict: # 没有设置点位状态,点位状态使用默认值
|
||||
cursor.execute(
|
||||
"""INSERT INTO form_data
|
||||
(form_id, row_index, x, y, z, rx, ry, rz, name)
|
||||
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)""",
|
||||
(
|
||||
form_id,
|
||||
row[0],
|
||||
row[1],
|
||||
row[2],
|
||||
row[3],
|
||||
row[4],
|
||||
row[5],
|
||||
row[6],
|
||||
row[7],
|
||||
),
|
||||
)
|
||||
else:
|
||||
# 从状态字典pos_state_dict中提取数据
|
||||
pos_name = pos_state_dict.get("pos_name", "normal")
|
||||
speed = pos_state_dict.get("speed", 20.0)
|
||||
tool_id = pos_state_dict.get("tool_id", 0)
|
||||
workpiece_id = pos_state_dict.get("work_id", 0)
|
||||
joint_values = pos_state_dict.get("joint_values", [-9999.0] * 6)
|
||||
j1, j2, j3, j4, j5, j6 = joint_values[:6]
|
||||
motion_type = pos_state_dict.get("motion_type", "直线")
|
||||
blend_time = pos_state_dict.get("blend_time", -1)
|
||||
|
||||
cursor.execute(
|
||||
"""INSERT INTO form_data
|
||||
(form_id, row_index, x, y, z, rx, ry, rz, name,
|
||||
speed, tool_id, workpiece_id, j1, j2, j3, j4, j5, j6, motion_type, blend_time)
|
||||
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)""",
|
||||
(
|
||||
form_id, # 1. form_id
|
||||
row[0], # 2. row_index
|
||||
row[1], # 3. x
|
||||
row[2], # 4. y
|
||||
row[3], # 5. z
|
||||
row[4], # 6. rx
|
||||
row[5], # 7. ry
|
||||
row[6], # 8. rz
|
||||
pos_name, # 9. name # 以点位状态中的 pos_name 为准
|
||||
speed, # 10. speed
|
||||
tool_id, # 11. tool_id
|
||||
workpiece_id, # 12. workpiece_id
|
||||
j1, # 13. j1
|
||||
j2, # 14. j2
|
||||
j3, # 15. j3
|
||||
j4, # 16. j4
|
||||
j5, # 17. j5
|
||||
j6, # 18. j6
|
||||
motion_type, # 19. motion_type
|
||||
blend_time, # 20. blend_time
|
||||
),
|
||||
)
|
||||
|
||||
except Exception as exc:
|
||||
self.rollback_and_close()
|
||||
raise exc
|
||||
|
||||
def get_form_data(self, form_id):
|
||||
"""
|
||||
根据form_id查询表单数据, 返回所有的表单数据
|
||||
返回格式为:
|
||||
data_rows = [
|
||||
[row_idx, x, y, z, rx, ry, rz, name, pos_state_dict],
|
||||
...
|
||||
]
|
||||
"""
|
||||
try:
|
||||
cursor = self.__connect()
|
||||
# 查询指定form_id的所有数据行,并按row_index排序
|
||||
cursor.execute(
|
||||
"""SELECT
|
||||
row_index, x, y, z, rx, ry, rz, name,
|
||||
speed, tool_id, workpiece_id, j1, j2, j3, j4, j5, j6,
|
||||
motion_type, blend_time
|
||||
FROM form_data
|
||||
WHERE form_id = ?
|
||||
ORDER BY row_index""",
|
||||
(form_id,),
|
||||
)
|
||||
|
||||
data_rows = []
|
||||
# 遍历查询结果
|
||||
for row in cursor.fetchall():
|
||||
# 解析基础坐标数据
|
||||
row_idx = row[0]
|
||||
x, y, z, rx, ry, rz = row[1:7]
|
||||
name = row[7]
|
||||
|
||||
# 解析 点位状态数据并构建字典
|
||||
speed = row[8]
|
||||
tool_id = row[9]
|
||||
work_id = row[10] #
|
||||
j1, j2, j3, j4, j5, j6 = row[11:17]
|
||||
motion_type = row[17]
|
||||
blend_time = row[18]
|
||||
|
||||
pos_state_dict = {
|
||||
"pos_name": name, # 保持与插入时一致,使用name作为pos_name
|
||||
"speed": speed,
|
||||
"tool_id": tool_id,
|
||||
"work_id": work_id,
|
||||
"joint_values": [j1, j2, j3, j4, j5, j6],
|
||||
"motion_type": motion_type,
|
||||
"blend_time": blend_time,
|
||||
}
|
||||
|
||||
# 构建一行的数据
|
||||
data_row = [row_idx, x, y, z, rx, ry, rz, name, pos_state_dict]
|
||||
data_rows.append(data_row)
|
||||
|
||||
return data_rows
|
||||
|
||||
except Exception as exc:
|
||||
self.rollback_and_close()
|
||||
raise exc
|
||||
@ -354,7 +472,7 @@ class DatabaseSaveThread(QThread):
|
||||
super().__init__()
|
||||
self.db_path = db_path
|
||||
self.form_name = form_name
|
||||
self.data_rows = data_rows # 主线程传递过来的UI数据
|
||||
self.data_rows = data_rows # UI线程传递过来的UI数据
|
||||
self.user_choice = None # 存储用户选择(True=覆盖,False=取消)
|
||||
self.mutex = QMutex()
|
||||
self.condition = QWaitCondition()
|
||||
@ -383,12 +501,15 @@ class DatabaseSaveThread(QThread):
|
||||
|
||||
# 用户选择覆盖:删除旧数据
|
||||
db.delete_form_data(exist_form_id)
|
||||
|
||||
# 插入新数据(复用exist_form_id)
|
||||
# 新增对点位状态的保存
|
||||
db.insert_form_data(exist_form_id, self.data_rows)
|
||||
self.result_signal.emit(f"表单「{self.form_name}」已覆盖并保存")
|
||||
|
||||
else:
|
||||
# 表单不存在:直接新增
|
||||
# 新增对点位状态的保存
|
||||
new_form_id = db.add_new_form(self.form_name)
|
||||
db.insert_form_data(new_form_id, self.data_rows)
|
||||
self.result_signal.emit(f"表单「{self.form_name}」已保存")
|
||||
@ -418,11 +539,11 @@ class DatabaseSaveThread(QThread):
|
||||
|
||||
# 数据库读取操作线程
|
||||
class DatabaseReadThread(QThread):
|
||||
# 信号1: 从form_info 读取所有的 id-name 发送
|
||||
# 信号1: 从form_info表 读取所有的 id-name 发送
|
||||
# [(form_id1, form_name1),...]
|
||||
form_id_name_signal = Signal(list)
|
||||
|
||||
# 信号2: 从 from_data 读取所有的 选择的表单的数据发送
|
||||
# 信号2: 从 from_data表 读取所有的 选择的表单的数据发送
|
||||
# {form_name1: data_rows1, ...}
|
||||
form_data_signal = Signal(dict)
|
||||
|
||||
@ -458,7 +579,7 @@ class DatabaseReadThread(QThread):
|
||||
|
||||
form_date_dict = dict()
|
||||
for form_id, form_name in self.selected_form_id_name:
|
||||
data_rows = db.get_row_idx_coordinate_and_name(form_id)
|
||||
data_rows = db.get_form_data(form_id)
|
||||
form_date_dict[form_name] = data_rows
|
||||
|
||||
self.form_data_signal.emit(form_date_dict)
|
||||
@ -499,6 +620,12 @@ class CoordinateTableWidget(QWidget):
|
||||
self.has_valid_copy = False # 标志是否进行了有效的复制(复制了一行的数据)
|
||||
self.setObjectName("CoordinateTableWidget")
|
||||
|
||||
# 状态编辑界面的临时数据
|
||||
# 状态编辑后点击应用保存在这里
|
||||
# 临时编辑数据:{标识符: 编辑后的状态(name、j1...)}
|
||||
# name需要特殊处理
|
||||
self.edited_state_dict = {}
|
||||
|
||||
# 主布局
|
||||
self.mainLayout = QVBoxLayout(self)
|
||||
self.mainLayout.setContentsMargins(30, 30, 30, 30)
|
||||
@ -536,9 +663,12 @@ class CoordinateTableWidget(QWidget):
|
||||
if self.initRowCount:
|
||||
self.table.setRowCount(5) # 表的行数
|
||||
|
||||
self.table.setColumnCount(7) # 表的列数
|
||||
# 新增第八列保存 毫秒级时间戳
|
||||
self.table.setColumnCount(8) # 表的列数
|
||||
|
||||
self.table.setHorizontalHeaderLabels(["x", "y", "z", "rx", "ry", "rz", "name"])
|
||||
self.table.setHorizontalHeaderLabels(
|
||||
["x", "y", "z", "rx", "ry", "rz", "name", "timestamp"]
|
||||
)
|
||||
self.table.horizontalHeader().setStyleSheet(
|
||||
"QHeaderView::section {font-size: 19px; font-weight: bold;}"
|
||||
)
|
||||
@ -546,6 +676,9 @@ class CoordinateTableWidget(QWidget):
|
||||
"QHeaderView::section {font-size: 14px; font-weight: bold;}"
|
||||
)
|
||||
|
||||
# 第八列(索引7)不显示 (通常不需要显示时间戳[唯一标识])
|
||||
self.table.setColumnHidden(7, True)
|
||||
|
||||
if self.hideVHeader:
|
||||
self.table.verticalHeader().hide() # 隐藏行标题(行名)
|
||||
|
||||
@ -608,7 +741,7 @@ class CoordinateTableWidget(QWidget):
|
||||
|
||||
# 状态编辑按钮
|
||||
self.stateEditBtn = PushButton("状态编辑")
|
||||
# self.stateEditBtn.clicked.connect(self.moveRowDown)
|
||||
self.stateEditBtn.clicked.connect(self.onStateEdit)
|
||||
btnLayout2.addWidget(self.stateEditBtn)
|
||||
|
||||
self.mainLayout.addLayout(btnLayout) # 添加 按钮布局一
|
||||
@ -616,13 +749,14 @@ class CoordinateTableWidget(QWidget):
|
||||
|
||||
# 数据保存到数据库,获取数据时调用
|
||||
def get_ui_data(self):
|
||||
"""从表格UI中获取数据 [[行索引row_idx, x, y, z, rx, ry, rz, name], ......]"""
|
||||
"""获取数据 [[行索引row_idx, x, y, z, rx, ry, rz, name, pos_state], ......]"""
|
||||
row_count = self.table.rowCount()
|
||||
# column_count = self.table.columnCount()
|
||||
# 这里的 data_rows 保存 [[行索引row_idx, x, y, z, rx, ry, rz, name, pos_state], ......]
|
||||
data_rows = []
|
||||
for row_idx in range(row_count):
|
||||
row_data = [row_idx] # 先保存行索引
|
||||
is_valid_row = True # 标记当前行是否完全有效
|
||||
is_valid_cood = True # 标记当前行的坐标是否完全有效
|
||||
|
||||
# 这里只有前6列是 x, y, z, rx, ry, rz
|
||||
# 目前 从ui获取的 需要保存到数据库的 只有 x, y, z, rx, ry, rz
|
||||
@ -634,7 +768,7 @@ class CoordinateTableWidget(QWidget):
|
||||
# 对于非法数据 和 不完整数据,不保存在数据库
|
||||
# 1、判断填写的 x, y, z, rx, ry, rz中是否有为空的坐标
|
||||
if not item or not item.text().strip():
|
||||
is_valid_row = False
|
||||
is_valid_cood = False
|
||||
break # 跳过这一行数据,保存下一行数据
|
||||
|
||||
# 2、检查填写的坐标是否都为数字
|
||||
@ -642,24 +776,40 @@ class CoordinateTableWidget(QWidget):
|
||||
try:
|
||||
coord_num = float(coord_str) # 尝试转换为数字
|
||||
except ValueError:
|
||||
is_valid_row = False
|
||||
is_valid_cood = False
|
||||
break # 跳过这一行数据,保存下一行数据
|
||||
|
||||
# 保存单个坐标,浮点类型
|
||||
row_data.append(coord_num)
|
||||
|
||||
# 新增:点位名字
|
||||
# 增加点位名字的判断,当点位名 为空时,使用默认的 "normal"
|
||||
name_idx = 6 # 目前的点位名的列索引为6 (索引从0开始)
|
||||
name_item = self.table.item(row_idx, name_idx)
|
||||
if not name_item or not name_item.text().strip():
|
||||
row_data.append("normal")
|
||||
else:
|
||||
pos_name = name_item.text().strip()
|
||||
row_data.append(pos_name)
|
||||
# 前面的坐标数据都有效,才保存到数据库
|
||||
if is_valid_cood:
|
||||
# 新增:点位名字
|
||||
# 增加点位名字的判断,当点位名 为空时,使用默认的 "normal"
|
||||
name_idx = 6 # 目前的点位名的列索引为6 (索引从0开始)
|
||||
name_item = self.table.item(row_idx, name_idx)
|
||||
if not name_item or not name_item.text().strip():
|
||||
row_data.append("normal")
|
||||
else:
|
||||
pos_name = name_item.text().strip()
|
||||
row_data.append(pos_name)
|
||||
|
||||
# 放入这一行的数据 行索引row_idx, x, y, z, rx, ry, rz, name
|
||||
if is_valid_row: # 有效,才保存到数据库
|
||||
# 新增:点位状态 pos_state, pos_state的类型为字典
|
||||
timestamp_idx = 7 # 目前的时间戳的列索引为7
|
||||
timestamp_item = self.table.item(row_idx, timestamp_idx)
|
||||
timestamp = (
|
||||
int(timestamp_item.text().strip())
|
||||
if (timestamp_item and timestamp_item.text().strip())
|
||||
else -1 # 表示没有进行状态编辑
|
||||
)
|
||||
|
||||
# 从edited_state_dict取 点位状态
|
||||
state_dict = (
|
||||
self.edited_state_dict.get(timestamp, {}) if timestamp != -1 else {}
|
||||
) # 点位状态的字典
|
||||
row_data.append(state_dict)
|
||||
|
||||
# 放入这一行的数据 行索引row_idx, x, y, z, rx, ry, rz, name, pos_state
|
||||
data_rows.append(row_data)
|
||||
|
||||
# print("data_rows", data_rows)
|
||||
@ -723,12 +873,14 @@ class CoordinateTableWidget(QWidget):
|
||||
self.table.setVerticalHeaderItem(row, header_item)
|
||||
|
||||
name_idx = 6 # 点位名的列索引号
|
||||
|
||||
for col in range(self.table.columnCount()):
|
||||
item = (
|
||||
QTableWidgetItem("")
|
||||
if col != name_idx
|
||||
else QTableWidgetItem("normal")
|
||||
)
|
||||
|
||||
item.setTextAlignment(Qt.AlignCenter)
|
||||
self.setThemeTextColor(item)
|
||||
self.table.setItem(row, col, item)
|
||||
@ -745,6 +897,7 @@ class CoordinateTableWidget(QWidget):
|
||||
msg_box.setStyleSheet("QLabel{color: black;}")
|
||||
msg_box.exec()
|
||||
|
||||
# 外界用于设置坐标的接口
|
||||
def update_table_data(self, positionList=None):
|
||||
selectedRows = self.getSelectedRows()
|
||||
for row in selectedRows:
|
||||
@ -899,6 +1052,7 @@ class CoordinateTableWidget(QWidget):
|
||||
return
|
||||
|
||||
# 获取UI数据
|
||||
# 目前,一行的点位数据包含了 点位状态 pos_state_dict
|
||||
data_rows = self.get_ui_data()
|
||||
if not data_rows:
|
||||
self.status_label.setText("没有数据可以保存, 请检查数据有效性!!!")
|
||||
@ -1059,10 +1213,77 @@ class CoordinateTableWidget(QWidget):
|
||||
# 5. 更新状态提示
|
||||
self.status_label.setText(f"第{current_row+1}行已下移至第{target_row+1}行")
|
||||
|
||||
# 状态编辑
|
||||
def onStateEdit(self):
|
||||
selected_rows = self.getSelectedRows()
|
||||
# 目前只支持对一行进行状态编辑
|
||||
if len(selected_rows) != 1:
|
||||
self.showNoSelectWarning("请仅选中一行进行状态编辑!!!")
|
||||
return
|
||||
|
||||
# 需要进行状态编辑的行的 行索引
|
||||
selected_row_idx = selected_rows[0]
|
||||
|
||||
# 获取到该行的 点位名称,列索引为6
|
||||
name_col_idx = 6
|
||||
|
||||
name_item = self.table.item(selected_row_idx, name_col_idx)
|
||||
|
||||
# 此时的点位名 为空,则使用默认的 mormal,表示普通点
|
||||
position_name = (
|
||||
name_item.text().strip()
|
||||
if name_item and name_item.text().strip()
|
||||
else "normal"
|
||||
)
|
||||
|
||||
# print(position_name)
|
||||
# 状态编辑对话框
|
||||
# 传入 点位名称, 选中行的行索引 (一行)
|
||||
status_diog = StatusEditDialog(position_name, selected_row_idx, self)
|
||||
|
||||
# 获取该行的时间戳(唯一标识)[重要]
|
||||
# 时间戳的 列索引为7
|
||||
timestamp_col_idx = 7
|
||||
timestamp_item = self.table.item(selected_row_idx, timestamp_col_idx)
|
||||
# 如果存在时间戳,那么就需要读取相应的 点位状态,并设置到状态编辑界面
|
||||
if timestamp_item and timestamp_item.text().strip():
|
||||
timestamp = int(timestamp_item.text().strip())
|
||||
status_diog.setPointStateValue(self.edited_state_dict[timestamp])
|
||||
|
||||
# 状态编辑界面点击应用按钮,保存状态编辑数据
|
||||
status_diog.point_state_applied.connect(self.onSaveStateEdit)
|
||||
|
||||
status_diog.exec()
|
||||
|
||||
# 保存 编辑的 点位状态
|
||||
def onSaveStateEdit(self, selected_row_idx: int, point_state: PointState):
|
||||
# 需要保存为 {唯一的值1 : 状态字典1, 唯一的值2 : 状态字典2, ...}
|
||||
# 唯一的值?时间戳作为唯一值
|
||||
# 1、时间戳
|
||||
unique_key = int(time.time() * 1000) # 毫秒级时间戳
|
||||
|
||||
self.edited_state_dict[unique_key] = point_state.to_dict()
|
||||
|
||||
# 2. 设置当前行的隐藏列(列索引为7)为 当前时间戳
|
||||
timestamp_idx = 7 # 当前,时间戳在表格中的索引为 7 (点位名称的后一个)
|
||||
timestamp_item = QTableWidgetItem(str(unique_key))
|
||||
timestamp_item.setTextAlignment(Qt.AlignCenter)
|
||||
self.setThemeTextColor(timestamp_item)
|
||||
self.table.setItem(selected_row_idx, timestamp_idx, timestamp_item)
|
||||
|
||||
# 3、同步点位的名称,显示到表格
|
||||
name_idx = 6 # 当前,点位名称在表格中的索引为 6
|
||||
name_item = QTableWidgetItem(str(point_state.pos_name))
|
||||
name_item.setTextAlignment(Qt.AlignCenter)
|
||||
self.setThemeTextColor(name_item)
|
||||
self.table.setItem(selected_row_idx, name_idx, name_item)
|
||||
|
||||
# print("onSaveStateEdit\n", self.edited_state_dict)
|
||||
|
||||
# ================交换两行数据=======================
|
||||
def _swapTwoRows(self, row1, row2):
|
||||
"""交换表格中两行的所有列数据(包括坐标和name列)"""
|
||||
total_cols = self.table.columnCount() # 7列(x/y/z/rx/ry/rz/name)
|
||||
total_cols = self.table.columnCount() # 8列(x/y/z/rx/ry/rz/name/timestamp)
|
||||
|
||||
for col in range(total_cols):
|
||||
# 1. 取出两行当前列的item(takeItem会移除原位置item,避免引用冲突)
|
||||
@ -1153,6 +1374,7 @@ class CoordinateFormsWidget(QWidget):
|
||||
self.initFirstForm()
|
||||
|
||||
# 初始化样式,应用主题样式
|
||||
# 后续使用 qss 文件
|
||||
self.applyThemeStyle()
|
||||
|
||||
def applyThemeStyle(self):
|
||||
@ -1510,7 +1732,7 @@ class CoordinateFormsWidget(QWidget):
|
||||
# 由读取的数据生成新表单
|
||||
def generateNewForms(self, form_data):
|
||||
"""根据读取到的数据生成新表单(UI线程处理)"""
|
||||
# form_data格式:{form_name: [(row_idx, x, y, z, rx, ry, rz, name), ...], ...}
|
||||
# form_data格式:{form_name: [(row_idx, x, y, z, rx, ry, rz, name, pos_state_dict), ...], ...}
|
||||
# print("form_data", form_data)
|
||||
for form_name, data_rows in form_data.items():
|
||||
# 创建新表单
|
||||
@ -1522,12 +1744,18 @@ class CoordinateFormsWidget(QWidget):
|
||||
new_form.move_to_coodinate_signal.connect(self.form_move_signal)
|
||||
|
||||
# 填充数据到新表单(包含点位名)
|
||||
for row_idx, x, y, z, rx, ry, rz, name in data_rows:
|
||||
for row_idx, x, y, z, rx, ry, rz, name, pos_state_dict in data_rows:
|
||||
# print(row_idx, x, y, z, rx, ry, rz)
|
||||
# 如果数单行数超过表格行数,自动添加行
|
||||
while row_idx >= new_form.table.rowCount():
|
||||
new_form.addNewRow()
|
||||
|
||||
# 这里获取一个唯一值作为 点位状态的标识 (就是前面的时间戳)
|
||||
unique_key = self.getPositionStateUniqueKey(row_idx)
|
||||
|
||||
# 将获取到的点位状态 保存到 创建的新表单的edited_state_dict中
|
||||
new_form.edited_state_dict[unique_key] = pos_state_dict
|
||||
|
||||
# 填充单元格
|
||||
new_form.table.setItem(row_idx, 0, QTableWidgetItem(str(x)))
|
||||
new_form.table.setItem(row_idx, 1, QTableWidgetItem(str(y)))
|
||||
@ -1537,7 +1765,10 @@ class CoordinateFormsWidget(QWidget):
|
||||
new_form.table.setItem(row_idx, 5, QTableWidgetItem(str(rz)))
|
||||
new_form.table.setItem(row_idx, 6, QTableWidgetItem(str(name)))
|
||||
|
||||
# 将填充的数据设置居中显示,一共是 0 到 6(如上),共7列
|
||||
# 时间戳(唯一标识)
|
||||
new_form.table.setItem(row_idx, 7, QTableWidgetItem(str(unique_key)))
|
||||
|
||||
# 将填充的数据设置居中显示,一共是 0 到 6(如上),共7列 (不包括时间戳,时间戳不显示)
|
||||
for col_idx in range(7):
|
||||
new_form.table.item(row_idx, col_idx).setTextAlignment(
|
||||
Qt.AlignCenter
|
||||
@ -1550,6 +1781,11 @@ class CoordinateFormsWidget(QWidget):
|
||||
)
|
||||
self.formStack.addWidget(new_form)
|
||||
|
||||
# 点状态唯一标识
|
||||
def getPositionStateUniqueKey(self, row_idx):
|
||||
unique_key = int(time.time() * 1000) + row_idx
|
||||
return unique_key
|
||||
|
||||
|
||||
# 更新表单中选中行数据 x,y,z,rx,ry,rz
|
||||
# def test(form_obj: CoordinateTableWidget):
|
||||
|
||||
382
app/view/mi_an/status_edit_dialog.py
Normal file
382
app/view/mi_an/status_edit_dialog.py
Normal file
@ -0,0 +1,382 @@
|
||||
from PySide6.QtCore import Qt, Signal
|
||||
from PySide6.QtWidgets import (
|
||||
QApplication,
|
||||
QWidget,
|
||||
QVBoxLayout,
|
||||
QHBoxLayout,
|
||||
QFormLayout,
|
||||
QGroupBox,
|
||||
QDialog,
|
||||
)
|
||||
from qfluentwidgets import (
|
||||
PushButton,
|
||||
ComboBox,
|
||||
DoubleSpinBox,
|
||||
SpinBox,
|
||||
setTheme,
|
||||
Theme,
|
||||
StrongBodyLabel,
|
||||
EditableComboBox,
|
||||
RadioButton,
|
||||
isDarkTheme,
|
||||
MessageBox,
|
||||
)
|
||||
from ...model.point_state import PointState
|
||||
|
||||
|
||||
class StatusEditDialog(QDialog):
|
||||
point_state_applied = Signal(int, PointState)
|
||||
|
||||
def __init__(self, pos_name, selected_row_idx, parent=None):
|
||||
super().__init__(parent)
|
||||
# 窗口基本设置
|
||||
self.setWindowTitle("状态编辑") # 设置窗口标题
|
||||
self.resize(600, 660) # 窗口大小
|
||||
self.setMinimumSize(550, 560) # 最小尺寸限制
|
||||
|
||||
# 点位名称
|
||||
self.pos_name = pos_name
|
||||
|
||||
# 选中行的行索引
|
||||
self.selected_row_idx = selected_row_idx
|
||||
|
||||
self.__initWidget()
|
||||
|
||||
def __initWidget(self):
|
||||
# 创建控件
|
||||
self.__createWidget()
|
||||
|
||||
# 设置样式
|
||||
self.__initStyles()
|
||||
|
||||
# 设置布局
|
||||
self.__initLayout()
|
||||
|
||||
# 绑定
|
||||
self.__bind()
|
||||
|
||||
# 创建相关控件
|
||||
def __createWidget(self):
|
||||
# 1. 点位名称输入
|
||||
self.name_combo = EditableComboBox()
|
||||
|
||||
self.name_combo.addItems(
|
||||
["抓取点", "破袋点", "震动点", "扔袋点", "相机/待抓点"]
|
||||
)
|
||||
|
||||
# 检查点位名称在下拉框是否已经存在
|
||||
target_pos_name = self.pos_name
|
||||
pos_name_index = self.name_combo.findText(target_pos_name)
|
||||
# 若未找到(索引=-1),则添加 表单中 的点位名字
|
||||
if pos_name_index == -1:
|
||||
self.name_combo.addItem(self.pos_name)
|
||||
# 选中新添加的这项
|
||||
new_index = self.name_combo.count() - 1
|
||||
self.name_combo.setCurrentIndex(new_index)
|
||||
else:
|
||||
# 已经存在的话就直接选中
|
||||
self.name_combo.setCurrentIndex(pos_name_index)
|
||||
|
||||
self.name_combo.setPlaceholderText("请设置点位名称")
|
||||
|
||||
# 2. 工具坐标系id
|
||||
self.tool_coord_spin = SpinBox()
|
||||
self.tool_coord_spin.setRange(0, 99) # 0-99范围
|
||||
self.tool_coord_spin.setValue(0) # 默认值
|
||||
self.tool_coord_btn = PushButton("获取当前工具坐标id")
|
||||
|
||||
# 3. 工件坐标系id
|
||||
self.work_coord_spin = SpinBox()
|
||||
self.work_coord_spin.setRange(0, 99) # 0-99范围
|
||||
self.work_coord_spin.setValue(0) # 默认值
|
||||
self.work_coord_btn = PushButton("获取当前工件坐标id")
|
||||
|
||||
# 4-9. 关节坐标 J1 到 J6
|
||||
self.j_spins = []
|
||||
for _ in range(6):
|
||||
spin = DoubleSpinBox()
|
||||
spin.setRange(-180, 180) # 角度范围 (-180度到180度)
|
||||
spin.setDecimals(3) # 保留3位小数
|
||||
spin.setSingleStep(0.001) # 默认步长
|
||||
self.j_spins.append(spin)
|
||||
|
||||
# 关节坐标默认值 (默认为无效值)
|
||||
self.j_spins[0].setValue(-9999)
|
||||
self.j_spins[1].setValue(-9999)
|
||||
self.j_spins[2].setValue(-9999)
|
||||
self.j_spins[3].setValue(-9999)
|
||||
self.j_spins[4].setValue(-9999)
|
||||
self.j_spins[5].setValue(-9999)
|
||||
|
||||
# 关节坐标设置 右侧的步长设置 和 获取关节坐标按钮
|
||||
self.step_group = QGroupBox("单击步长设置")
|
||||
self.step_input = DoubleSpinBox()
|
||||
self.step_input.setRange(0.001, 180.0) # 步长范围
|
||||
self.step_input.setDecimals(3) # 保留3位小数
|
||||
self.step_input.setValue(0.001) # 默认步长
|
||||
self.get_values_btn = PushButton("获取当前J1-J6值")
|
||||
|
||||
# 10. 速度 (移动速度)
|
||||
self.approach_speed_spin = DoubleSpinBox()
|
||||
self.approach_speed_spin.setRange(0, 100)
|
||||
self.approach_speed_spin.setDecimals(0) # 小数点
|
||||
self.approach_speed_spin.setValue(20)
|
||||
self.approach_speed_spin.setSingleStep(10)
|
||||
|
||||
# 11. 运动类型(下拉选择)
|
||||
self.motion_type_combo = ComboBox()
|
||||
self.motion_type_combo.addItems(["直线", "曲线中间点", "曲线终点", "自由路径"])
|
||||
|
||||
# 12. 平滑选择
|
||||
self.stop_radio = RadioButton("停止")
|
||||
self.smooth_radio = RadioButton("平滑过渡")
|
||||
self.smooth_ms_spin = DoubleSpinBox() # 平滑过渡的时间(毫秒)
|
||||
self.smooth_ms_spin.setRange(0, 500) # 范围:0 - 500 ms
|
||||
self.smooth_ms_spin.setDecimals(0) # 整数毫秒
|
||||
self.smooth_ms_spin.setValue(0) # 默认值0
|
||||
self.smooth_ms_spin.setSingleStep(10) # 步长:10毫秒
|
||||
self.smooth_ms_spin.setEnabled(False) # 初始禁用(仅“平滑过渡”选中时启用)
|
||||
self.stop_radio.setChecked(True) # 默认选“停止”
|
||||
|
||||
# 13. 应用按钮
|
||||
self.apply_btn = PushButton("应用")
|
||||
self.apply_btn.setMinimumWidth(160) # 按钮最小宽度
|
||||
|
||||
def __initStyles(self):
|
||||
# 根据主题设置样式表
|
||||
if isDarkTheme(): # 深色主题
|
||||
self.step_group.setStyleSheet(
|
||||
"""
|
||||
QGroupBox {
|
||||
color: white; /* 标题文字颜色 */
|
||||
border: 1px solid white; /* 边框线条颜色和宽度 */
|
||||
border-radius: 6px; /* 边框圆角 */
|
||||
margin-top: 10px; /* 标题与边框的距离 */
|
||||
}
|
||||
QGroupBox::title {
|
||||
subcontrol-origin: margin;
|
||||
subcontrol-position: top left; /* 标题位置 */
|
||||
left: 10px; /* 标题左边距 */
|
||||
padding: 0 3px 0 3px; /* 标题内边距 */
|
||||
}
|
||||
"""
|
||||
)
|
||||
self.setStyleSheet("background-color: rgb(32, 32, 32);")
|
||||
else: # 浅色主题
|
||||
self.step_group.setStyleSheet(
|
||||
"""
|
||||
QGroupBox {
|
||||
color: black; /* 标题文字颜色 */
|
||||
border: 1px solid black; /* 边框线条颜色和宽度 */
|
||||
border-radius: 6px; /* 边框圆角 */
|
||||
margin-top: 10px; /* 标题与边框的距离 */
|
||||
}
|
||||
QGroupBox::title {
|
||||
subcontrol-origin: margin;
|
||||
subcontrol-position: top left; /* 标题位置 */
|
||||
left: 10px; /* 标题左边距 */
|
||||
padding: 0 3px 0 3px; /* 标题内边距 */
|
||||
}
|
||||
"""
|
||||
)
|
||||
self.setStyleSheet("background-color: rgb(243, 243, 243);")
|
||||
|
||||
def __initLayout(self):
|
||||
# 主布局(直接应用于当前Widget)
|
||||
main_layout = QVBoxLayout(self)
|
||||
main_layout.setContentsMargins(24, 24, 24, 24) # 边距
|
||||
main_layout.setSpacing(16) # 控件间距
|
||||
|
||||
# 表单布局(管理标签和输入框)
|
||||
form_layout = QFormLayout()
|
||||
form_layout.setRowWrapPolicy(QFormLayout.DontWrapRows) # 不自动换行
|
||||
# 标签右对齐+垂直居中
|
||||
form_layout.setLabelAlignment(Qt.AlignRight | Qt.AlignVCenter)
|
||||
form_layout.setSpacing(12) # 表单行间距
|
||||
|
||||
# 1. 添加点位名称布局
|
||||
form_layout.addRow(StrongBodyLabel("点位名称"), self.name_combo)
|
||||
|
||||
# 2. 添加工具坐标布局
|
||||
tool_coord_layout = QHBoxLayout()
|
||||
tool_coord_layout.addWidget(self.tool_coord_spin)
|
||||
tool_coord_layout.addWidget(self.tool_coord_btn)
|
||||
form_layout.addRow(StrongBodyLabel("工具坐标id"), tool_coord_layout)
|
||||
|
||||
# 3. 添加工件坐标布局
|
||||
work_coord_layout = QHBoxLayout() # 工件坐标水平布局
|
||||
work_coord_layout.addWidget(self.work_coord_spin)
|
||||
work_coord_layout.addWidget(self.work_coord_btn)
|
||||
form_layout.addRow(StrongBodyLabel("工件坐标id"), work_coord_layout)
|
||||
|
||||
# 4-9 关节坐标布局
|
||||
joint_control_layout = QHBoxLayout()
|
||||
|
||||
# 左侧:关节角输入(J1-J6)
|
||||
joint_input_layout = QFormLayout()
|
||||
joint_input_layout.setRowWrapPolicy(QFormLayout.DontWrapRows)
|
||||
joint_input_layout.setLabelAlignment(Qt.AlignRight | Qt.AlignVCenter)
|
||||
joint_input_layout.setSpacing(12)
|
||||
|
||||
for index in range(6):
|
||||
joint_input_layout.addRow(
|
||||
StrongBodyLabel(f"J{index + 1} (°)"), self.j_spins[index]
|
||||
)
|
||||
|
||||
# 将关节坐标输入布局 添加到 关节坐标布局
|
||||
joint_control_layout.addLayout(joint_input_layout)
|
||||
|
||||
# 右侧:步长设置和获取按钮
|
||||
control_panel_layout = QVBoxLayout()
|
||||
control_panel_layout.setSpacing(16)
|
||||
step_layout = QVBoxLayout(self.step_group)
|
||||
step_layout.setContentsMargins(10, 15, 10, 15)
|
||||
step_layout.setSpacing(10)
|
||||
step_layout.addWidget(self.step_input)
|
||||
|
||||
# step_layout添加到控制面板布局
|
||||
control_panel_layout.addWidget(self.step_group)
|
||||
control_panel_layout.addWidget(self.get_values_btn)
|
||||
control_panel_layout.addStretch() # 拉伸项,使内容靠上
|
||||
|
||||
# 将 控制面板布局(右侧) 添加到 关节控制布局
|
||||
joint_control_layout.addLayout(control_panel_layout)
|
||||
|
||||
# 将关节控制水平布局添加到表单布局
|
||||
form_layout.addRow(StrongBodyLabel("关节坐标"), joint_control_layout)
|
||||
|
||||
# 10. 速度布局
|
||||
form_layout.addRow(StrongBodyLabel("速度 (%)"), self.approach_speed_spin)
|
||||
|
||||
# 11. 运动类型(下拉选择)布局
|
||||
form_layout.addRow(StrongBodyLabel("运动类型"), self.motion_type_combo)
|
||||
|
||||
# 12. "在此点" 平滑选择布局
|
||||
stop_layout = QHBoxLayout()
|
||||
stop_layout.addWidget(self.stop_radio)
|
||||
stop_layout.addWidget(self.smooth_radio)
|
||||
stop_layout.addWidget(self.smooth_ms_spin)
|
||||
stop_layout.addWidget(StrongBodyLabel("ms"))
|
||||
stop_layout.setAlignment(Qt.AlignLeft) # 与标签左对齐
|
||||
form_layout.addRow(StrongBodyLabel("在此点"), stop_layout)
|
||||
|
||||
# 将表单布局添加到主布局
|
||||
main_layout.addLayout(form_layout)
|
||||
|
||||
# 13. 底部按钮布局(居中显示)
|
||||
btn_layout = QHBoxLayout()
|
||||
btn_layout.setAlignment(Qt.AlignHCenter) # 水平居中
|
||||
btn_layout.addWidget(self.apply_btn)
|
||||
|
||||
# 将底部按钮布局添加到主布局
|
||||
main_layout.addLayout(btn_layout)
|
||||
|
||||
# 让表单控件顶部对齐
|
||||
main_layout.addStretch(1)
|
||||
|
||||
def __bind(self):
|
||||
# 更新 J1 到 J6 的步长
|
||||
self.step_input.valueChanged.connect(self.onUpdateStepSize)
|
||||
|
||||
# 获取 J1 到 J6 的值(外部相关)
|
||||
self.get_values_btn.clicked.connect(self.onGetJointValues)
|
||||
|
||||
# 调整平滑时间设置控件可不可用
|
||||
self.stop_radio.toggled.connect(
|
||||
lambda checked: self.smooth_ms_spin.setEnabled(not checked)
|
||||
)
|
||||
self.smooth_radio.toggled.connect(
|
||||
lambda checked: self.smooth_ms_spin.setEnabled(checked)
|
||||
)
|
||||
|
||||
# 应用按钮点击 (外部相关)
|
||||
self.apply_btn.clicked.connect(self.onApplyBtnClicked)
|
||||
|
||||
# 设置状态编辑框中的 点位的状态
|
||||
def setPointStateValue(self, pos_state_dict: dict):
|
||||
# 设置除了点位名字之外的所有 点位状态的值
|
||||
self.approach_speed_spin.setValue(pos_state_dict["speed"])
|
||||
self.tool_coord_spin.setValue(pos_state_dict["tool_id"])
|
||||
self.work_coord_spin.setValue(pos_state_dict["work_id"])
|
||||
for index in range(6):
|
||||
self.j_spins[index].setValue(pos_state_dict["joint_values"][index])
|
||||
|
||||
# 运动状态设置
|
||||
# 查找目标文本对应的索引
|
||||
target_motion_type = pos_state_dict["motion_type"]
|
||||
# 1. 查找目标文本对应的索引
|
||||
motion_index = self.motion_type_combo.findText(target_motion_type)
|
||||
# 2. 若未找到(索引=-1),默认选中第0项;否则选中对应索引
|
||||
if motion_index == -1:
|
||||
self.motion_type_combo.setCurrentIndex(0)
|
||||
else:
|
||||
self.motion_type_combo.setCurrentIndex(motion_index)
|
||||
|
||||
if pos_state_dict["blend_time"] == -1: # 此时为 停止
|
||||
self.stop_radio.setChecked(True)
|
||||
else:
|
||||
self.smooth_radio.setChecked(True)
|
||||
self.smooth_ms_spin.setValue(pos_state_dict["blend_time"])
|
||||
|
||||
def onUpdateStepSize(self, value):
|
||||
"""更新所有关节角输入框的步长"""
|
||||
for spin in self.j_spins:
|
||||
spin.setSingleStep(value)
|
||||
|
||||
def onGetJointValues(self):
|
||||
"""获取J1-J6的值(这里用示例值模拟)"""
|
||||
# 实际应用中,这里应该从设备或其他数据源获取值
|
||||
# 这里用随机值模拟
|
||||
import random
|
||||
|
||||
for i in range(6):
|
||||
# 生成一个-180到180之间的随机数,保留3位小数
|
||||
value = round(random.uniform(-180, 180), 3)
|
||||
self.j_spins[i].setValue(value)
|
||||
print("已获取并更新J1-J6的值")
|
||||
|
||||
def onApplyBtnClicked(self):
|
||||
"""应用按钮点击事件处理"""
|
||||
# 1、获取点名称
|
||||
pos_name = self.name_combo.text()
|
||||
# 2、速度
|
||||
speed = self.approach_speed_spin.value()
|
||||
# 3、tool_id
|
||||
tool_id = self.tool_coord_spin.value()
|
||||
# 4、work_id
|
||||
work_id = self.work_coord_spin.value()
|
||||
# 5-10、所有关节坐标 J1 到 J6
|
||||
joint_values = [spin.value() for spin in self.j_spins]
|
||||
# 11、运动类型 (直线、 曲线中间点、 曲线终点、 自由路径)
|
||||
motion_type = self.motion_type_combo.currentText()
|
||||
# 12、平滑时间(停止=-1,否则取输入值)
|
||||
blend_time = -1 if self.stop_radio.isChecked() else self.smooth_ms_spin.value()
|
||||
|
||||
try:
|
||||
point_state = PointState(
|
||||
pos_name=pos_name,
|
||||
speed=speed,
|
||||
tool_id=tool_id,
|
||||
work_id=work_id,
|
||||
joint_values=joint_values,
|
||||
motion_type=motion_type,
|
||||
blend_time=blend_time,
|
||||
)
|
||||
# print("状态编辑结果:", point_state.__str__())
|
||||
|
||||
# 发送信号给 表单窗口 CoordinateTableWidget对象
|
||||
self.point_state_applied.emit(self.selected_row_idx, point_state)
|
||||
|
||||
# 关闭状态编辑窗口
|
||||
self.close()
|
||||
except ValueError as e:
|
||||
# 捕获校验错误,弹窗提示用户
|
||||
MessageBox("状态错误", str(e), self).exec()
|
||||
|
||||
|
||||
# if __name__ == "__main__":
|
||||
# app = QApplication([])
|
||||
# setTheme(Theme.DARK) # 设置浅色主题(可选:Theme.DARK)
|
||||
# widget = StatusEditWidget()
|
||||
# widget.show() # 显示窗口
|
||||
# app.exec()
|
||||
Reference in New Issue
Block a user