add (增加了main_controller 和 位置设定的点位上移和下移)
This commit is contained in:
53
app/controller/mi_an/main_controller.py
Normal file
53
app/controller/mi_an/main_controller.py
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
from ...view.mi_an_main_window import Window as MainWindow
|
||||||
|
from ...view.cood_forms_interface import CoordinateFormsWidget
|
||||||
|
|
||||||
|
from typing import TypedDict
|
||||||
|
|
||||||
|
|
||||||
|
# 子界面管理
|
||||||
|
class SubViewsDict(TypedDict):
|
||||||
|
position: CoordinateFormsWidget
|
||||||
|
|
||||||
|
|
||||||
|
class MainController:
|
||||||
|
def __init__(self):
|
||||||
|
# 主界面
|
||||||
|
self.main_window = MainWindow()
|
||||||
|
|
||||||
|
# 初始化子界面
|
||||||
|
self._initSubViews()
|
||||||
|
|
||||||
|
# 初始化子控制器
|
||||||
|
self._initSubControllers()
|
||||||
|
|
||||||
|
self.__connectSignals()
|
||||||
|
|
||||||
|
def _initSubViews(self):
|
||||||
|
self.sub_views: SubViewsDict = {
|
||||||
|
"system": self.main_window.system, # 系统设置
|
||||||
|
"product": self.main_window.product, # 生产界面
|
||||||
|
"robot": self.main_window.robot, # 机器臂基础设置
|
||||||
|
"io": self.main_window.io, # io面板
|
||||||
|
"position": self.main_window.position.formsWidget, # 点位设置
|
||||||
|
"basic": self.main_window.basic, # 基础设置
|
||||||
|
"point": self.main_window.point, # 点位调试
|
||||||
|
"other": self.main_window.other, # 其他设置
|
||||||
|
"data": self.main_window.data, # 数据采集
|
||||||
|
}
|
||||||
|
|
||||||
|
def _initSubControllers(self):
|
||||||
|
# self.sub_controllers = {
|
||||||
|
# "system": SystemController(self.sub_views["system"]),
|
||||||
|
# "produce": ProduceController(self.sub_views["produce"]),
|
||||||
|
# }
|
||||||
|
pass
|
||||||
|
|
||||||
|
def showMainWindow(self):
|
||||||
|
self.main_window.show()
|
||||||
|
|
||||||
|
def __connectSignals(self):
|
||||||
|
pass
|
||||||
|
self.sub_views["position"].form_move_signal.connect(self.handleMove)
|
||||||
|
|
||||||
|
def handleMove(self, pos_list: list):
|
||||||
|
print("handleMove 移动:", pos_list)
|
||||||
@ -115,20 +115,51 @@ class FormDatabase:
|
|||||||
)
|
)
|
||||||
|
|
||||||
# 创建表单数据表form_data(存储每行数据)
|
# 创建表单数据表form_data(存储每行数据)
|
||||||
|
# cursor.execute(
|
||||||
|
# """
|
||||||
|
# CREATE TABLE IF NOT EXISTS form_data (
|
||||||
|
# data_id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||||
|
# form_id INTEGER NOT NULL, -- 关联表单信息表的 form_id
|
||||||
|
# row_index INTEGER NOT NULL, -- 行号(从0开始)
|
||||||
|
# x TEXT,
|
||||||
|
# y TEXT,
|
||||||
|
# z TEXT,
|
||||||
|
# rx TEXT,
|
||||||
|
# ry TEXT,
|
||||||
|
# rz TEXT,
|
||||||
|
# FOREIGN KEY (form_id) REFERENCES form_info(form_id) ON DELETE CASCADE,
|
||||||
|
# UNIQUE(form_id, row_index) -- 确保一行数据只存一次
|
||||||
|
# )
|
||||||
|
# """
|
||||||
|
# )
|
||||||
|
|
||||||
cursor.execute(
|
cursor.execute(
|
||||||
"""
|
"""
|
||||||
CREATE TABLE IF NOT EXISTS form_data (
|
CREATE TABLE IF NOT EXISTS form_data (
|
||||||
data_id INTEGER PRIMARY KEY AUTOINCREMENT,
|
data_id INTEGER PRIMARY KEY AUTOINCREMENT, --ID
|
||||||
form_id INTEGER NOT NULL, -- 关联表单信息表的 form_id
|
form_id INTEGER NOT NULL, --关联form_info表的 form_id
|
||||||
row_index INTEGER NOT NULL, -- 行号(从0开始)
|
row_index INTEGER NOT NULL, --表单中的行号(从0开始)
|
||||||
x TEXT,
|
x DOUBLE NOT NULL, --X轴坐标(单位:mm)
|
||||||
y TEXT,
|
y DOUBLE NOT NULL, --Y轴坐标(单位:mm)
|
||||||
z TEXT,
|
z DOUBLE NOT NULL, --Z轴坐标(单位:mm)
|
||||||
rx TEXT,
|
rx DOUBLE NOT NULL, --绕X轴旋转角度(单位:°)
|
||||||
ry TEXT,
|
ry DOUBLE NOT NULL, --绕Y轴旋转角度(单位:°)
|
||||||
rz TEXT,
|
rz DOUBLE NOT NULL, --绕Z轴旋转角度(单位:°)
|
||||||
|
name VARCHAR(50) NOT NULL DEFAULT 'normal', --点位名(如“取料点”)
|
||||||
|
speed DOUBLE NOT NULL DEFAULT 20.0, --移动速度
|
||||||
|
tool_id INTEGER NOT NULL DEFAULT 0, --工具ID(如夹爪、吸盘)
|
||||||
|
workpiece_id INTEGER NOT NULL DEFAULT 0, --工件ID
|
||||||
|
j1 DOUBLE NOT NULL DEFAULT -9999.0, --关节角度j1(单位:°)
|
||||||
|
j2 DOUBLE NOT NULL DEFAULT -9999.0, --关节角度j2(单位:°)
|
||||||
|
j3 DOUBLE NOT NULL DEFAULT -9999.0, --关节角度j3(单位:°)
|
||||||
|
j4 DOUBLE NOT NULL DEFAULT -9999.0, --关节角度j4(单位:°)
|
||||||
|
j5 DOUBLE NOT NULL DEFAULT -9999.0, --关节角度j5(单位:°)
|
||||||
|
j6 DOUBLE NOT NULL DEFAULT -9999.0, --关节角度j6(单位:°)
|
||||||
|
ext1 DOUBLE, --扩展字段1
|
||||||
|
ext2 INTEGER, --扩展字段2
|
||||||
|
ext3 TEXT, --扩展字段3
|
||||||
FOREIGN KEY (form_id) REFERENCES form_info(form_id) ON DELETE CASCADE,
|
FOREIGN KEY (form_id) REFERENCES form_info(form_id) ON DELETE CASCADE,
|
||||||
UNIQUE(form_id, row_index) -- 确保一行数据只存一次
|
UNIQUE(form_id, row_index)
|
||||||
)
|
)
|
||||||
"""
|
"""
|
||||||
)
|
)
|
||||||
@ -157,11 +188,13 @@ class FormDatabase:
|
|||||||
"""连接数据库并获取游标"""
|
"""连接数据库并获取游标"""
|
||||||
if not self.conn:
|
if not self.conn:
|
||||||
self.conn = sqlite3.connect(self.db_path)
|
self.conn = sqlite3.connect(self.db_path)
|
||||||
|
self.conn.execute("PRAGMA foreign_keys = ON;") # 启用外键
|
||||||
self.cursor = self.conn.cursor()
|
self.cursor = self.conn.cursor()
|
||||||
return self.cursor
|
return self.cursor
|
||||||
|
|
||||||
def commit_and_close(self):
|
def commit_and_close(self):
|
||||||
"""提交事务并关闭连接"""
|
"""提交事务并关闭连接"""
|
||||||
|
# 数据库操作最终一定要调用
|
||||||
if self.conn:
|
if self.conn:
|
||||||
self.conn.commit() # 提交事务
|
self.conn.commit() # 提交事务
|
||||||
self.conn.close() # 关闭连接
|
self.conn.close() # 关闭连接
|
||||||
@ -192,8 +225,9 @@ class FormDatabase:
|
|||||||
self.rollback_and_close()
|
self.rollback_and_close()
|
||||||
raise exc
|
raise exc
|
||||||
|
|
||||||
|
# 只删除(清空)表单的数据
|
||||||
def delete_form_data(self, form_id):
|
def delete_form_data(self, form_id):
|
||||||
"""删除指定表单的所有数据"""
|
"""删除指定表单的所有数据(表单数据form_data表中的该表单的数据)"""
|
||||||
try:
|
try:
|
||||||
cursor = self.__connect()
|
cursor = self.__connect()
|
||||||
cursor.execute("DELETE FROM form_data WHERE form_id = ?", (form_id,))
|
cursor.execute("DELETE FROM form_data WHERE form_id = ?", (form_id,))
|
||||||
@ -201,6 +235,19 @@ class FormDatabase:
|
|||||||
self.rollback_and_close()
|
self.rollback_and_close()
|
||||||
raise exc
|
raise exc
|
||||||
|
|
||||||
|
# 删除 表单
|
||||||
|
def delete_form(self, form_id):
|
||||||
|
"""删除指定表单, 包括 表单信息表中表单信息 以及 数据表中的对应数据"""
|
||||||
|
try:
|
||||||
|
cursor = self.__connect()
|
||||||
|
# 利用外键,只需要删除表单信息form_info表中的表单信息
|
||||||
|
# 数据表中的对应数据 会被自动删除
|
||||||
|
# 备注:SQLite的外键默认不开启,需要在 __connect中启用外键
|
||||||
|
cursor.execute("DELETE FROM form_info WHERE form_id = ?", (form_id,))
|
||||||
|
except Exception as exc:
|
||||||
|
self.rollback_and_close()
|
||||||
|
raise exc
|
||||||
|
|
||||||
def add_new_form(self, form_name):
|
def add_new_form(self, form_name):
|
||||||
"""新增表单 (返回新表单的form_id)"""
|
"""新增表单 (返回新表单的form_id)"""
|
||||||
try:
|
try:
|
||||||
@ -219,9 +266,19 @@ class FormDatabase:
|
|||||||
# row格式: [row_idx, x, y, z, rx, ry, rz]
|
# row格式: [row_idx, x, y, z, rx, ry, rz]
|
||||||
cursor.execute(
|
cursor.execute(
|
||||||
"""INSERT INTO form_data
|
"""INSERT INTO form_data
|
||||||
(form_id, row_index, x, y, z, rx, ry, rz)
|
(form_id, row_index, x, y, z, rx, ry, rz, name)
|
||||||
VALUES (?, ?, ?, ?, ?, ?, ?, ?)""",
|
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)""",
|
||||||
(form_id, row[0], row[1], row[2], row[3], row[4], row[5], row[6]),
|
(
|
||||||
|
form_id,
|
||||||
|
row[0],
|
||||||
|
row[1],
|
||||||
|
row[2],
|
||||||
|
row[3],
|
||||||
|
row[4],
|
||||||
|
row[5],
|
||||||
|
row[6],
|
||||||
|
row[7],
|
||||||
|
),
|
||||||
)
|
)
|
||||||
except Exception as exc:
|
except Exception as exc:
|
||||||
self.rollback_and_close()
|
self.rollback_and_close()
|
||||||
@ -257,6 +314,22 @@ class FormDatabase:
|
|||||||
self.rollback_and_close()
|
self.rollback_and_close()
|
||||||
raise exc
|
raise exc
|
||||||
|
|
||||||
|
def get_row_idx_coordinate_and_name(self, form_id):
|
||||||
|
"""根据form_id查询对应的表单数据 data_rows (包含行索引row_idx, x, y, z, rx, ry, rz, name)"""
|
||||||
|
try:
|
||||||
|
cursor = self.__connect()
|
||||||
|
cursor.execute(
|
||||||
|
"SELECT row_index, x, y, z, rx, ry, rz, name FROM form_data "
|
||||||
|
"WHERE form_id = ?",
|
||||||
|
(form_id,),
|
||||||
|
)
|
||||||
|
# [(row_idx, x, y, z, rx, ry, rz, name), ...]
|
||||||
|
data_rows = cursor.fetchall()
|
||||||
|
return data_rows
|
||||||
|
except Exception as exc:
|
||||||
|
self.rollback_and_close()
|
||||||
|
raise exc
|
||||||
|
|
||||||
def get_sorted_coordinate_list(self, form_name):
|
def get_sorted_coordinate_list(self, form_name):
|
||||||
"""
|
"""
|
||||||
form_name 等同于线名
|
form_name 等同于线名
|
||||||
@ -385,7 +458,7 @@ class DatabaseReadThread(QThread):
|
|||||||
|
|
||||||
form_date_dict = dict()
|
form_date_dict = dict()
|
||||||
for form_id, form_name in self.selected_form_id_name:
|
for form_id, form_name in self.selected_form_id_name:
|
||||||
data_rows = db.get_row_idx_coordinate_list(form_id)
|
data_rows = db.get_row_idx_coordinate_and_name(form_id)
|
||||||
form_date_dict[form_name] = data_rows
|
form_date_dict[form_name] = data_rows
|
||||||
|
|
||||||
self.form_data_signal.emit(form_date_dict)
|
self.form_data_signal.emit(form_date_dict)
|
||||||
@ -423,6 +496,7 @@ class CoordinateTableWidget(QWidget):
|
|||||||
self.form_name = form_name
|
self.form_name = form_name
|
||||||
self.hideVHeader = hideVHeader # 是否隐藏行名
|
self.hideVHeader = hideVHeader # 是否隐藏行名
|
||||||
self.initRowCount = initRowCount # 是否需要初始的行数
|
self.initRowCount = initRowCount # 是否需要初始的行数
|
||||||
|
self.has_valid_copy = False # 标志是否进行了有效的复制(复制了一行的数据)
|
||||||
self.setObjectName("CoordinateTableWidget")
|
self.setObjectName("CoordinateTableWidget")
|
||||||
|
|
||||||
# 主布局
|
# 主布局
|
||||||
@ -462,9 +536,9 @@ class CoordinateTableWidget(QWidget):
|
|||||||
if self.initRowCount:
|
if self.initRowCount:
|
||||||
self.table.setRowCount(5) # 表的行数
|
self.table.setRowCount(5) # 表的行数
|
||||||
|
|
||||||
self.table.setColumnCount(6) # 表的列数
|
self.table.setColumnCount(7) # 表的列数
|
||||||
|
|
||||||
self.table.setHorizontalHeaderLabels(["x", "y", "z", "rx", "ry", "rz"])
|
self.table.setHorizontalHeaderLabels(["x", "y", "z", "rx", "ry", "rz", "name"])
|
||||||
self.table.horizontalHeader().setStyleSheet(
|
self.table.horizontalHeader().setStyleSheet(
|
||||||
"QHeaderView::section {font-size: 19px; font-weight: bold;}"
|
"QHeaderView::section {font-size: 19px; font-weight: bold;}"
|
||||||
)
|
)
|
||||||
@ -475,7 +549,7 @@ class CoordinateTableWidget(QWidget):
|
|||||||
if self.hideVHeader:
|
if self.hideVHeader:
|
||||||
self.table.verticalHeader().hide() # 隐藏行标题(行名)
|
self.table.verticalHeader().hide() # 隐藏行标题(行名)
|
||||||
|
|
||||||
for i in range(6):
|
for i in range(7):
|
||||||
self.table.horizontalHeader().setSectionResizeMode(
|
self.table.horizontalHeader().setSectionResizeMode(
|
||||||
i, self.table.horizontalHeader().ResizeMode.Stretch
|
i, self.table.horizontalHeader().ResizeMode.Stretch
|
||||||
)
|
)
|
||||||
@ -507,8 +581,8 @@ class CoordinateTableWidget(QWidget):
|
|||||||
self.resetBtn.clicked.connect(self.resetSelectedRow)
|
self.resetBtn.clicked.connect(self.resetSelectedRow)
|
||||||
btnLayout.addWidget(self.resetBtn)
|
btnLayout.addWidget(self.resetBtn)
|
||||||
|
|
||||||
# 移动按钮
|
# 机器臂(人)移动按钮
|
||||||
self.readBtn = PushButton("移动")
|
self.readBtn = PushButton("机器移动")
|
||||||
self.readBtn.setIcon(FIF.RIGHT_ARROW.icon()) # FOLDER
|
self.readBtn.setIcon(FIF.RIGHT_ARROW.icon()) # FOLDER
|
||||||
self.readBtn.clicked.connect(self.moveToSelectedCoodinate)
|
self.readBtn.clicked.connect(self.moveToSelectedCoodinate)
|
||||||
btnLayout.addWidget(self.readBtn)
|
btnLayout.addWidget(self.readBtn)
|
||||||
@ -519,11 +593,30 @@ class CoordinateTableWidget(QWidget):
|
|||||||
self.saveBtn.clicked.connect(self.saveToDatabase) # 关联保存函数
|
self.saveBtn.clicked.connect(self.saveToDatabase) # 关联保存函数
|
||||||
btnLayout.addWidget(self.saveBtn)
|
btnLayout.addWidget(self.saveBtn)
|
||||||
|
|
||||||
self.mainLayout.addLayout(btnLayout)
|
btnLayout2 = QHBoxLayout()
|
||||||
|
btnLayout2.setSpacing(15)
|
||||||
|
|
||||||
|
# 上移按钮
|
||||||
|
self.moveUpBtn = PushButton("上移")
|
||||||
|
self.moveUpBtn.clicked.connect(self.moveRowUp)
|
||||||
|
btnLayout2.addWidget(self.moveUpBtn)
|
||||||
|
|
||||||
|
# 下移按钮
|
||||||
|
self.moveDownBtn = PushButton("下移")
|
||||||
|
self.moveDownBtn.clicked.connect(self.moveRowDown)
|
||||||
|
btnLayout2.addWidget(self.moveDownBtn)
|
||||||
|
|
||||||
|
# 状态编辑按钮
|
||||||
|
self.stateEditBtn = PushButton("状态编辑")
|
||||||
|
# self.stateEditBtn.clicked.connect(self.moveRowDown)
|
||||||
|
btnLayout2.addWidget(self.stateEditBtn)
|
||||||
|
|
||||||
|
self.mainLayout.addLayout(btnLayout) # 添加 按钮布局一
|
||||||
|
self.mainLayout.addLayout(btnLayout2) # 添加 按钮布局二
|
||||||
|
|
||||||
# 数据保存到数据库,获取数据时调用
|
# 数据保存到数据库,获取数据时调用
|
||||||
def get_ui_data(self):
|
def get_ui_data(self):
|
||||||
"""从表格UI中获取数据 [[行索引row_idx, x, y, z, rx, ry, rz], ......]"""
|
"""从表格UI中获取数据 [[行索引row_idx, x, y, z, rx, ry, rz, name], ......]"""
|
||||||
row_count = self.table.rowCount()
|
row_count = self.table.rowCount()
|
||||||
# column_count = self.table.columnCount()
|
# column_count = self.table.columnCount()
|
||||||
data_rows = []
|
data_rows = []
|
||||||
@ -531,7 +624,7 @@ class CoordinateTableWidget(QWidget):
|
|||||||
row_data = [row_idx] # 先保存行索引
|
row_data = [row_idx] # 先保存行索引
|
||||||
is_valid_row = True # 标记当前行是否完全有效
|
is_valid_row = True # 标记当前行是否完全有效
|
||||||
|
|
||||||
# 这里只有前6列是 x, y, rx, ry, rz
|
# 这里只有前6列是 x, y, z, rx, ry, rz
|
||||||
# 目前 从ui获取的 需要保存到数据库的 只有 x, y, z, rx, ry, rz
|
# 目前 从ui获取的 需要保存到数据库的 只有 x, y, z, rx, ry, rz
|
||||||
# 故这里为 0到5
|
# 故这里为 0到5
|
||||||
for col_idx in range(6):
|
for col_idx in range(6):
|
||||||
@ -555,10 +648,21 @@ class CoordinateTableWidget(QWidget):
|
|||||||
# 保存单个坐标,浮点类型
|
# 保存单个坐标,浮点类型
|
||||||
row_data.append(coord_num)
|
row_data.append(coord_num)
|
||||||
|
|
||||||
# 放入这一行的数据 行索引row_idx, x, y, z, rx, ry, rz
|
# 新增:点位名字
|
||||||
|
# 增加点位名字的判断,当点位名 为空时,使用默认的 "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: # 有效,才保存到数据库
|
if is_valid_row: # 有效,才保存到数据库
|
||||||
data_rows.append(row_data)
|
data_rows.append(row_data)
|
||||||
|
|
||||||
|
# print("data_rows", data_rows)
|
||||||
return data_rows
|
return data_rows
|
||||||
|
|
||||||
def showConfirmDialog(self):
|
def showConfirmDialog(self):
|
||||||
@ -618,8 +722,13 @@ class CoordinateTableWidget(QWidget):
|
|||||||
self.setThemeTextColor(header_item)
|
self.setThemeTextColor(header_item)
|
||||||
self.table.setVerticalHeaderItem(row, header_item)
|
self.table.setVerticalHeaderItem(row, header_item)
|
||||||
|
|
||||||
|
name_idx = 6 # 点位名的列索引号
|
||||||
for col in range(self.table.columnCount()):
|
for col in range(self.table.columnCount()):
|
||||||
item = QTableWidgetItem("")
|
item = (
|
||||||
|
QTableWidgetItem("")
|
||||||
|
if col != name_idx
|
||||||
|
else QTableWidgetItem("normal")
|
||||||
|
)
|
||||||
item.setTextAlignment(Qt.AlignCenter)
|
item.setTextAlignment(Qt.AlignCenter)
|
||||||
self.setThemeTextColor(item)
|
self.setThemeTextColor(item)
|
||||||
self.table.setItem(row, col, item)
|
self.table.setItem(row, col, item)
|
||||||
@ -639,7 +748,8 @@ class CoordinateTableWidget(QWidget):
|
|||||||
def update_table_data(self, positionList=None):
|
def update_table_data(self, positionList=None):
|
||||||
selectedRows = self.getSelectedRows()
|
selectedRows = self.getSelectedRows()
|
||||||
for row in selectedRows:
|
for row in selectedRows:
|
||||||
for col in range(self.table.columnCount()):
|
# x, y, z, rx, ry, rz 的索引为 0 到 5
|
||||||
|
for col in range(6):
|
||||||
item = QTableWidgetItem(
|
item = QTableWidgetItem(
|
||||||
str(positionList[col])
|
str(positionList[col])
|
||||||
if (positionList and 0 <= col < len(positionList))
|
if (positionList and 0 <= col < len(positionList))
|
||||||
@ -650,10 +760,10 @@ class CoordinateTableWidget(QWidget):
|
|||||||
self.table.setItem(row, col, item)
|
self.table.setItem(row, col, item)
|
||||||
|
|
||||||
if positionList:
|
if positionList:
|
||||||
self.status_label.setText(f"已将选中行设置为{positionList}")
|
self.status_label.setText(f"已将选中行点位设置为{positionList}")
|
||||||
else:
|
else:
|
||||||
self.status_label.setText(
|
self.status_label.setText(
|
||||||
"已将选中行设置为[-9999, -9999, -9999, -9999, -9999, -9999]"
|
"已将选中行点位设置为[-9999, -9999, -9999, -9999, -9999, -9999]"
|
||||||
)
|
)
|
||||||
|
|
||||||
"""
|
"""
|
||||||
@ -675,8 +785,11 @@ class CoordinateTableWidget(QWidget):
|
|||||||
self.updateRowHeaders()
|
self.updateRowHeaders()
|
||||||
|
|
||||||
# 初始化单元格
|
# 初始化单元格
|
||||||
|
name_idx = 6 # 点位名的列索引号
|
||||||
for col in range(self.table.columnCount()):
|
for col in range(self.table.columnCount()):
|
||||||
item = QTableWidgetItem("")
|
item = (
|
||||||
|
QTableWidgetItem("") if col != name_idx else QTableWidgetItem("normal")
|
||||||
|
)
|
||||||
item.setTextAlignment(Qt.AlignCenter)
|
item.setTextAlignment(Qt.AlignCenter)
|
||||||
self.setThemeTextColor(item)
|
self.setThemeTextColor(item)
|
||||||
self.table.setItem(insert_pos, col, item)
|
self.table.setItem(insert_pos, col, item)
|
||||||
@ -711,7 +824,7 @@ class CoordinateTableWidget(QWidget):
|
|||||||
self.showNoSelectWarning("请先选中再设置点位!")
|
self.showNoSelectWarning("请先选中再设置点位!")
|
||||||
return
|
return
|
||||||
|
|
||||||
# 选中行默认设置
|
# 选中行默认设置,主要是对 x, y, z, rx, ry, rz, 进行默认设置
|
||||||
self.update_table_data()
|
self.update_table_data()
|
||||||
|
|
||||||
# 发送选中行设置(更新)信号
|
# 发送选中行设置(更新)信号
|
||||||
@ -724,16 +837,19 @@ class CoordinateTableWidget(QWidget):
|
|||||||
self.showNoSelectWarning("请先选中再重置!")
|
self.showNoSelectWarning("请先选中再重置!")
|
||||||
return
|
return
|
||||||
|
|
||||||
|
# x, y, z, rx, ry, rz 的索引为 0到5,故这里为6
|
||||||
|
# 只重置 x, y, z, rx, ry, rz
|
||||||
|
cood_count = 6
|
||||||
for row in selectedRows:
|
for row in selectedRows:
|
||||||
for col in range(self.table.columnCount()):
|
for col in range(cood_count):
|
||||||
item = QTableWidgetItem("")
|
item = QTableWidgetItem("")
|
||||||
item.setTextAlignment(Qt.AlignCenter)
|
item.setTextAlignment(Qt.AlignCenter)
|
||||||
self.setThemeTextColor(item)
|
self.setThemeTextColor(item)
|
||||||
self.table.setItem(row, col, item)
|
self.table.setItem(row, col, item)
|
||||||
|
|
||||||
self.status_label.setText("已重置选中行")
|
self.status_label.setText("已重置选中行坐标点位")
|
||||||
|
|
||||||
# 移动
|
# 移动 (只进行移动操作)
|
||||||
def moveToSelectedCoodinate(self):
|
def moveToSelectedCoodinate(self):
|
||||||
selectedRows = self.getSelectedRows()
|
selectedRows = self.getSelectedRows()
|
||||||
if not selectedRows:
|
if not selectedRows:
|
||||||
@ -807,13 +923,21 @@ class CoordinateTableWidget(QWidget):
|
|||||||
return
|
return
|
||||||
|
|
||||||
menu = QMenu()
|
menu = QMenu()
|
||||||
copyAction = QAction("复制此行数据", self)
|
|
||||||
|
if self.has_valid_copy:
|
||||||
|
# 已经复制了有效的数据,可以进行粘贴操作
|
||||||
|
pasteAction = QAction("粘贴坐标到此行", self)
|
||||||
|
pasteAction.triggered.connect(self.pasteRowData)
|
||||||
|
menu.addAction(pasteAction)
|
||||||
|
else:
|
||||||
|
# 还没有进行复制,进行复制一行数据的操作
|
||||||
|
copyAction = QAction("复制此行坐标", self)
|
||||||
copyAction.triggered.connect(self.copyRowData)
|
copyAction.triggered.connect(self.copyRowData)
|
||||||
menu.addAction(copyAction)
|
menu.addAction(copyAction)
|
||||||
menu.exec(self.table.mapToGlobal(position))
|
menu.exec(self.table.mapToGlobal(position))
|
||||||
|
|
||||||
def copyRowData(self):
|
def copyRowData(self):
|
||||||
"""复制选中行数据到剪贴板"""
|
"""复制选中行数据到剪贴板 目前只复制选中行的 x, y, z, rx, ry, rz"""
|
||||||
selectedRows = self.getSelectedRows()
|
selectedRows = self.getSelectedRows()
|
||||||
if not selectedRows:
|
if not selectedRows:
|
||||||
return
|
return
|
||||||
@ -822,14 +946,141 @@ class CoordinateTableWidget(QWidget):
|
|||||||
# 选中多行,默认复制选中的多行中行数最小的那行
|
# 选中多行,默认复制选中的多行中行数最小的那行
|
||||||
row = selectedRows[0]
|
row = selectedRows[0]
|
||||||
rowData = []
|
rowData = []
|
||||||
for col in range(self.table.columnCount()):
|
cood_count = 6 # # x, y, z, rx, ry, rz 的列索引为 0 到 5,故这里为6
|
||||||
|
for col in range(cood_count):
|
||||||
item = self.table.item(row, col)
|
item = self.table.item(row, col)
|
||||||
rowData.append(item.text() if item else "")
|
rowData.append(item.text() if item else "")
|
||||||
|
|
||||||
dataStr = ", ".join(rowData)
|
dataStr = ", ".join(rowData)
|
||||||
clipboard = QApplication.clipboard()
|
clipboard = QApplication.clipboard()
|
||||||
clipboard.setText(dataStr)
|
clipboard.setText(dataStr)
|
||||||
self.status_label.setText(f"已复制第 {row + 1} 行的数据: {dataStr}")
|
|
||||||
|
# 显示结果
|
||||||
|
self.status_label.setText(f"已复制第 {row + 1} 行的坐标: {dataStr}")
|
||||||
|
# 更改复制状态
|
||||||
|
self.has_valid_copy = True
|
||||||
|
|
||||||
|
def pasteRowData(self):
|
||||||
|
"""从剪贴板粘贴数据到选中行"""
|
||||||
|
selectedRows = self.getSelectedRows()
|
||||||
|
if not selectedRows:
|
||||||
|
return
|
||||||
|
|
||||||
|
# 支持粘贴到所有的选中行
|
||||||
|
for target_row in selectedRows:
|
||||||
|
clipboard = QApplication.clipboard()
|
||||||
|
data_str = clipboard.text().strip()
|
||||||
|
if not data_str:
|
||||||
|
self.status_label.setText("剪贴板为空,无法粘贴!!!")
|
||||||
|
return
|
||||||
|
|
||||||
|
pasted_data = []
|
||||||
|
for item in data_str.split(","):
|
||||||
|
stripped_item = item.strip()
|
||||||
|
try:
|
||||||
|
pasted_data.append(float(stripped_item)) # 保存的格式为 float
|
||||||
|
except ValueError:
|
||||||
|
break
|
||||||
|
|
||||||
|
# x, y, z, rx, ry, rz 的列索引为 0 到 5,故这里为6
|
||||||
|
# 此时一共需要粘贴六个坐标
|
||||||
|
cood_count = 6
|
||||||
|
# print(pasted_data)
|
||||||
|
|
||||||
|
if len(pasted_data) != cood_count:
|
||||||
|
self.status_label.setText(
|
||||||
|
f"粘贴到第 {target_row + 1} 行失败, 复制的坐标{data_str}错误!!!"
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
for col in range(cood_count):
|
||||||
|
item = QTableWidgetItem(str(pasted_data[col]))
|
||||||
|
item.setTextAlignment(Qt.AlignCenter)
|
||||||
|
self.setThemeTextColor(item)
|
||||||
|
self.table.setItem(target_row, col, item)
|
||||||
|
|
||||||
|
# 提示粘贴结果(列出所有粘贴的行号)
|
||||||
|
row_nums = [str(row + 1) for row in selectedRows]
|
||||||
|
self.status_label.setText(
|
||||||
|
f"已将坐标{pasted_data}粘贴到第{', '.join(row_nums)}行"
|
||||||
|
)
|
||||||
|
|
||||||
|
# 粘贴后重置 复制状态,可以重新进行复制操作
|
||||||
|
self.has_valid_copy = False
|
||||||
|
|
||||||
|
# 上移操作
|
||||||
|
def moveRowUp(self):
|
||||||
|
"""将选中行上移一行(仅支持单行选中)"""
|
||||||
|
selectedRows = self.getSelectedRows()
|
||||||
|
# 1. 校验:仅支持单行上移
|
||||||
|
if len(selectedRows) != 1:
|
||||||
|
self.showNoSelectWarning("请仅选中一行进行上移操作!")
|
||||||
|
return
|
||||||
|
|
||||||
|
current_row = selectedRows[0]
|
||||||
|
# total_rows = self.table.rowCount()
|
||||||
|
|
||||||
|
# 2. 边界校验:第一行无法上移
|
||||||
|
if current_row == 0:
|
||||||
|
self.status_label.setText("当前行为第一行,无法上移!!!")
|
||||||
|
return
|
||||||
|
|
||||||
|
# 3. 交换当前行与上一行的数据
|
||||||
|
target_row = current_row - 1 # 上移的目标行(当前行的上一行)
|
||||||
|
self._swapTwoRows(current_row, target_row)
|
||||||
|
|
||||||
|
# 4. 保持选中状态(选中移动后的行)
|
||||||
|
self.table.selectRow(target_row)
|
||||||
|
# 5. 更新状态提示
|
||||||
|
self.status_label.setText(f"第{current_row+1}行已上移至第{target_row+1}行")
|
||||||
|
|
||||||
|
# 下移操作
|
||||||
|
def moveRowDown(self):
|
||||||
|
"""将选中行下移一行(仅支持单行选中)"""
|
||||||
|
selectedRows = self.getSelectedRows()
|
||||||
|
# 1. 校验:仅支持单行下移
|
||||||
|
if len(selectedRows) != 1:
|
||||||
|
self.showNoSelectWarning("请仅选中一行进行下移操作!!")
|
||||||
|
return
|
||||||
|
|
||||||
|
current_row = selectedRows[0]
|
||||||
|
total_rows = self.table.rowCount()
|
||||||
|
|
||||||
|
# 2. 边界校验:最后一行无法下移
|
||||||
|
if current_row == total_rows - 1:
|
||||||
|
self.status_label.setText("当前行为最后一行,无法下移!!!")
|
||||||
|
return
|
||||||
|
|
||||||
|
# 3. 交换当前行与下一行的数据
|
||||||
|
target_row = current_row + 1 # 下移的目标行(当前行的下一行)
|
||||||
|
self._swapTwoRows(current_row, target_row)
|
||||||
|
|
||||||
|
# 4. 保持选中状态(选中移动后的行)
|
||||||
|
self.table.selectRow(target_row)
|
||||||
|
# 5. 更新状态提示
|
||||||
|
self.status_label.setText(f"第{current_row+1}行已下移至第{target_row+1}行")
|
||||||
|
|
||||||
|
# ================交换两行数据=======================
|
||||||
|
def _swapTwoRows(self, row1, row2):
|
||||||
|
"""交换表格中两行的所有列数据(包括坐标和name列)"""
|
||||||
|
total_cols = self.table.columnCount() # 7列(x/y/z/rx/ry/rz/name)
|
||||||
|
|
||||||
|
for col in range(total_cols):
|
||||||
|
# 1. 取出两行当前列的item(takeItem会移除原位置item,避免引用冲突)
|
||||||
|
# 行1的当前列item
|
||||||
|
item1 = self.table.takeItem(row1, col) or QTableWidgetItem("")
|
||||||
|
# 行2的当前列item
|
||||||
|
item2 = self.table.takeItem(row2, col) or QTableWidgetItem("")
|
||||||
|
|
||||||
|
# 2. 交换设置item(行1放行2的item,行2放行1的item)
|
||||||
|
self.table.setItem(row1, col, item2)
|
||||||
|
self.table.setItem(row2, col, item1)
|
||||||
|
|
||||||
|
# 3. 确保交换后文本仍居中(保持样式一致性)
|
||||||
|
self.table.item(row1, col).setTextAlignment(Qt.AlignCenter)
|
||||||
|
self.table.item(row2, col).setTextAlignment(Qt.AlignCenter)
|
||||||
|
# 4. 确保文本颜色符合主题(浅色/深色)
|
||||||
|
self.setThemeTextColor(self.table.item(row1, col))
|
||||||
|
self.setThemeTextColor(self.table.item(row2, col))
|
||||||
|
|
||||||
def getSelectedRows(self):
|
def getSelectedRows(self):
|
||||||
return list(set(item.row() for item in self.table.selectedItems()))
|
return list(set(item.row() for item in self.table.selectedItems()))
|
||||||
@ -1066,6 +1317,7 @@ class CoordinateFormsWidget(QWidget):
|
|||||||
if isinstance(sender_form, CoordinateTableWidget):
|
if isinstance(sender_form, CoordinateTableWidget):
|
||||||
self.form_update_signal.emit(sender_form)
|
self.form_update_signal.emit(sender_form)
|
||||||
|
|
||||||
|
# 读取数据
|
||||||
def readFromDatabase(self):
|
def readFromDatabase(self):
|
||||||
"""启动读取线程,处理表单选择和数据生成"""
|
"""启动读取线程,处理表单选择和数据生成"""
|
||||||
# 检查是否已有运行中的读取线程
|
# 检查是否已有运行中的读取线程
|
||||||
@ -1074,7 +1326,7 @@ class CoordinateFormsWidget(QWidget):
|
|||||||
and self.read_thread
|
and self.read_thread
|
||||||
and self.read_thread.isRunning()
|
and self.read_thread.isRunning()
|
||||||
):
|
):
|
||||||
# self.status_label.setText("有未完成的数据库读取操作,请稍后再试......")
|
self.showStateWarning("有未完成的数据库读取操作,请稍后再试......")
|
||||||
return
|
return
|
||||||
|
|
||||||
# 创建读取线程
|
# 创建读取线程
|
||||||
@ -1086,12 +1338,12 @@ class CoordinateFormsWidget(QWidget):
|
|||||||
# 连接信号:接收表单数据,生成新表单
|
# 连接信号:接收表单数据,生成新表单
|
||||||
self.read_thread.form_data_signal.connect(self.generateNewForms)
|
self.read_thread.form_data_signal.connect(self.generateNewForms)
|
||||||
# 连接信号:状态提示 (数据库错误等)
|
# 连接信号:状态提示 (数据库错误等)
|
||||||
self.read_thread.state_signal.connect(self.showDatabaseReadWarning)
|
self.read_thread.state_signal.connect(self.showStateWarning)
|
||||||
|
|
||||||
# 启动线程
|
# 启动线程
|
||||||
self.read_thread.start()
|
self.read_thread.start()
|
||||||
|
|
||||||
def showDatabaseReadWarning(self, msg):
|
def showStateWarning(self, msg):
|
||||||
msg_box = QMessageBox(self)
|
msg_box = QMessageBox(self)
|
||||||
msg_box.setIcon(QMessageBox.Warning)
|
msg_box.setIcon(QMessageBox.Warning)
|
||||||
msg_box.setWindowTitle("提示")
|
msg_box.setWindowTitle("提示")
|
||||||
@ -1101,11 +1353,12 @@ class CoordinateFormsWidget(QWidget):
|
|||||||
msg_box.exec()
|
msg_box.exec()
|
||||||
|
|
||||||
def showFormSelection(self, all_form_id_name):
|
def showFormSelection(self, all_form_id_name):
|
||||||
"""显示多选表单选择页面 (UI线程处理)"""
|
"""显示多选表单选择页面 (UI线程处理), 新增右键可删除表单"""
|
||||||
if not all_form_id_name:
|
if not all_form_id_name:
|
||||||
# self.status_label.setText("数据库为空, 没有任何表单")
|
# self.status_label.setText("数据库为空, 没有任何表单")
|
||||||
self.read_thread.set_selected_forms(list())
|
# self.read_thread.set_selected_forms(list())
|
||||||
return
|
# return
|
||||||
|
pass # 直接进行后续操作,显示一个空的列表,表示数据库为空
|
||||||
|
|
||||||
# 提取表单名(用于列表显示)
|
# 提取表单名(用于列表显示)
|
||||||
form_names = [name for (_, name) in all_form_id_name]
|
form_names = [name for (_, name) in all_form_id_name]
|
||||||
@ -1138,6 +1391,14 @@ class CoordinateFormsWidget(QWidget):
|
|||||||
list_widget.addItems(form_names)
|
list_widget.addItems(form_names)
|
||||||
layout.addWidget(list_widget)
|
layout.addWidget(list_widget)
|
||||||
|
|
||||||
|
# ==========新增:右键可删除选中的表单 ======
|
||||||
|
list_widget.setContextMenuPolicy(Qt.CustomContextMenu)
|
||||||
|
list_widget.customContextMenuRequested.connect(
|
||||||
|
lambda position: self.showFormContextMenu(
|
||||||
|
list_widget, position, all_form_id_name
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
# 确认/取消按钮
|
# 确认/取消按钮
|
||||||
btn_layout = QHBoxLayout()
|
btn_layout = QHBoxLayout()
|
||||||
confirm_btn = PushButton("确认")
|
confirm_btn = PushButton("确认")
|
||||||
@ -1185,10 +1446,72 @@ class CoordinateFormsWidget(QWidget):
|
|||||||
# 显示表单选择框
|
# 显示表单选择框
|
||||||
dialog.exec()
|
dialog.exec()
|
||||||
|
|
||||||
|
def showFormContextMenu(self, list_widget, position, all_form_id_name):
|
||||||
|
"""右键菜单:删除选中表单"""
|
||||||
|
menu = QMenu()
|
||||||
|
delete_action = QAction("删除选中表单", self)
|
||||||
|
# 传递当前对话框实例,用于显示提示
|
||||||
|
delete_action.triggered.connect(
|
||||||
|
lambda: self.deleteSelectedForm(list_widget, all_form_id_name)
|
||||||
|
)
|
||||||
|
menu.addAction(delete_action)
|
||||||
|
menu.exec(list_widget.mapToGlobal(position))
|
||||||
|
|
||||||
|
def deleteSelectedForm(self, list_widget, all_form_id_name):
|
||||||
|
"""删除选中的一个或多个表单(支持批量删除)"""
|
||||||
|
selected_items = list_widget.selectedItems()
|
||||||
|
if not selected_items:
|
||||||
|
self.showStateWarning("请先选中要删除的表单!!")
|
||||||
|
return
|
||||||
|
|
||||||
|
# 1. 获取所有选中表单的 ID 和名称(支持批量)
|
||||||
|
selected_forms = [
|
||||||
|
(all_form_id_name[i][0], all_form_id_name[i][1]) # (form_id, form_name)
|
||||||
|
for i in range(len(all_form_id_name))
|
||||||
|
if list_widget.item(i).isSelected()
|
||||||
|
]
|
||||||
|
if not selected_forms:
|
||||||
|
return
|
||||||
|
|
||||||
|
# 2. 显示确认对话框(列出所有要删除的表单名)
|
||||||
|
form_names = ", ".join([name for (_, name) in selected_forms])
|
||||||
|
msg_box = QMessageBox()
|
||||||
|
msg_box.setWindowTitle("确认删除")
|
||||||
|
msg_box.setText(f"确定要删除以下表单吗?\n{form_names}")
|
||||||
|
msg_box.setStandardButtons(QMessageBox.Yes | QMessageBox.No)
|
||||||
|
msg_box.setStyleSheet("QLabel{color: black;}")
|
||||||
|
reply = msg_box.exec()
|
||||||
|
if reply != QMessageBox.Yes:
|
||||||
|
return
|
||||||
|
|
||||||
|
try:
|
||||||
|
# 3. 执行数据库删除(批量删除)
|
||||||
|
db = FormDatabase("db/forms.db")
|
||||||
|
db.init_database()
|
||||||
|
for form_id, _ in selected_forms:
|
||||||
|
db.delete_form(form_id) # 删除表单
|
||||||
|
db.commit_and_close() # 提交并关闭数据库连接
|
||||||
|
|
||||||
|
# 4. 刷新列表(重新读取数据库中的表单)
|
||||||
|
db_reload = FormDatabase("db/forms.db")
|
||||||
|
db_reload.init_database()
|
||||||
|
new_all_form_id_name = db_reload.get_all_form_id_name()
|
||||||
|
db_reload.commit_and_close()
|
||||||
|
|
||||||
|
# 更新列表显示
|
||||||
|
list_widget.clear()
|
||||||
|
list_widget.addItems([name for (_, name) in new_all_form_id_name])
|
||||||
|
|
||||||
|
# 更新状态提示
|
||||||
|
self.showStateWarning(f"已删除表单:{form_names}")
|
||||||
|
except Exception as e:
|
||||||
|
self.showStateWarning(f"删除失败:{str(e)}")
|
||||||
|
|
||||||
# 由读取的数据生成新表单
|
# 由读取的数据生成新表单
|
||||||
def generateNewForms(self, form_data):
|
def generateNewForms(self, form_data):
|
||||||
"""根据读取到的数据生成新表单(UI线程处理)"""
|
"""根据读取到的数据生成新表单(UI线程处理)"""
|
||||||
# form_data格式:{form_name: [(row_idx, x, y, z, rx, ry, rz), ...], ...}
|
# form_data格式:{form_name: [(row_idx, x, y, z, rx, ry, rz, name), ...], ...}
|
||||||
|
# print("form_data", form_data)
|
||||||
for form_name, data_rows in form_data.items():
|
for form_name, data_rows in form_data.items():
|
||||||
# 创建新表单
|
# 创建新表单
|
||||||
self.formTotalCnt += 1 # 创建的总的表单数加一
|
self.formTotalCnt += 1 # 创建的总的表单数加一
|
||||||
@ -1198,19 +1521,28 @@ class CoordinateFormsWidget(QWidget):
|
|||||||
new_form.update_table_signal.connect(self.handleFormUpdate)
|
new_form.update_table_signal.connect(self.handleFormUpdate)
|
||||||
new_form.move_to_coodinate_signal.connect(self.form_move_signal)
|
new_form.move_to_coodinate_signal.connect(self.form_move_signal)
|
||||||
|
|
||||||
# 填充数据到新表单
|
# 填充数据到新表单(包含点位名)
|
||||||
for row_idx, x, y, z, rx, ry, rz in data_rows:
|
for row_idx, x, y, z, rx, ry, rz, name in data_rows:
|
||||||
|
# print(row_idx, x, y, z, rx, ry, rz)
|
||||||
# 如果数单行数超过表格行数,自动添加行
|
# 如果数单行数超过表格行数,自动添加行
|
||||||
while row_idx >= new_form.table.rowCount():
|
while row_idx >= new_form.table.rowCount():
|
||||||
new_form.addNewRow()
|
new_form.addNewRow()
|
||||||
|
|
||||||
# 填充单元格
|
# 填充单元格
|
||||||
new_form.table.setItem(row_idx, 0, QTableWidgetItem(x))
|
new_form.table.setItem(row_idx, 0, QTableWidgetItem(str(x)))
|
||||||
new_form.table.setItem(row_idx, 1, QTableWidgetItem(y))
|
new_form.table.setItem(row_idx, 1, QTableWidgetItem(str(y)))
|
||||||
new_form.table.setItem(row_idx, 2, QTableWidgetItem(z))
|
new_form.table.setItem(row_idx, 2, QTableWidgetItem(str(z)))
|
||||||
new_form.table.setItem(row_idx, 3, QTableWidgetItem(rx))
|
new_form.table.setItem(row_idx, 3, QTableWidgetItem(str(rx)))
|
||||||
new_form.table.setItem(row_idx, 4, QTableWidgetItem(ry))
|
new_form.table.setItem(row_idx, 4, QTableWidgetItem(str(ry)))
|
||||||
new_form.table.setItem(row_idx, 5, QTableWidgetItem(rz))
|
new_form.table.setItem(row_idx, 5, QTableWidgetItem(str(rz)))
|
||||||
|
new_form.table.setItem(row_idx, 6, QTableWidgetItem(str(name)))
|
||||||
|
|
||||||
|
# 将填充的数据设置居中显示,一共是 0 到 6(如上),共7列
|
||||||
|
for col_idx in range(7):
|
||||||
|
new_form.table.item(row_idx, col_idx).setTextAlignment(
|
||||||
|
Qt.AlignCenter
|
||||||
|
)
|
||||||
|
|
||||||
# 将新表单添加到UI
|
# 将新表单添加到UI
|
||||||
form_key = f"form_{self.formTotalCnt}" # 唯一标识
|
form_key = f"form_{self.formTotalCnt}" # 唯一标识
|
||||||
self.tabBar.addTab(
|
self.tabBar.addTab(
|
||||||
@ -1224,12 +1556,14 @@ class CoordinateFormsWidget(QWidget):
|
|||||||
# form_obj.update_table_data([666, 666, 666, 666, 666, 666])
|
# form_obj.update_table_data([666, 666, 666, 666, 666, 666])
|
||||||
|
|
||||||
# 移动
|
# 移动
|
||||||
|
# def move_test(pos_list: list):
|
||||||
|
# print("移动:", pos_list)
|
||||||
|
|
||||||
# if __name__ == "__main__":
|
# if __name__ == "__main__":
|
||||||
# app = QApplication(sys.argv)
|
# app = QApplication(sys.argv)
|
||||||
# setTheme(Theme.DARK)
|
# setTheme(Theme.DARK)
|
||||||
# window = CoordinateFormsWidget()
|
# window = CoordinateFormsWidget()
|
||||||
# window.form_update_signal.connect(test)
|
# window.form_update_signal.connect(test)
|
||||||
|
# window.form_move_signal.connect(move_test)
|
||||||
# window.show()
|
# window.show()
|
||||||
# sys.exit(app.exec())
|
# sys.exit(app.exec())
|
||||||
|
|||||||
238
app/view/mi_an_main_window.py
Normal file
238
app/view/mi_an_main_window.py
Normal file
@ -0,0 +1,238 @@
|
|||||||
|
# coding:utf-8
|
||||||
|
import sys
|
||||||
|
import os
|
||||||
|
from PySide6.QtCore import Qt, QRect, QUrl, Signal
|
||||||
|
from PySide6.QtGui import (
|
||||||
|
QIcon,
|
||||||
|
QPainter,
|
||||||
|
QImage,
|
||||||
|
QBrush,
|
||||||
|
QColor,
|
||||||
|
QFont,
|
||||||
|
QDesktopServices,
|
||||||
|
)
|
||||||
|
from PySide6.QtWidgets import (
|
||||||
|
QApplication,
|
||||||
|
QFrame,
|
||||||
|
QStackedWidget,
|
||||||
|
QHBoxLayout,
|
||||||
|
QLabel,
|
||||||
|
QWidget,
|
||||||
|
)
|
||||||
|
|
||||||
|
from qfluentwidgets import (
|
||||||
|
NavigationInterface,
|
||||||
|
NavigationItemPosition,
|
||||||
|
NavigationWidget,
|
||||||
|
MessageBox,
|
||||||
|
isDarkTheme,
|
||||||
|
setTheme,
|
||||||
|
Theme,
|
||||||
|
setThemeColor,
|
||||||
|
qrouter,
|
||||||
|
FluentWindow,
|
||||||
|
NavigationAvatarWidget,
|
||||||
|
)
|
||||||
|
from qfluentwidgets import FluentIcon as FIF
|
||||||
|
from qframelesswindow import FramelessWindow, StandardTitleBar
|
||||||
|
|
||||||
|
from app.view.system_interface import SystemInterface
|
||||||
|
from app.view.produce_interface import ProduceInterface
|
||||||
|
from app.view.text_interface import TextInterface
|
||||||
|
from app.view.data_interface import DataInterface
|
||||||
|
|
||||||
|
from app.view.cood_forms_interface import CoodFormsInterface
|
||||||
|
|
||||||
|
|
||||||
|
class Widget(QFrame):
|
||||||
|
|
||||||
|
def __init__(self, text: str, parent=None):
|
||||||
|
super().__init__(parent=parent)
|
||||||
|
self.label = QLabel(text, self)
|
||||||
|
self.label.setAlignment(Qt.AlignCenter)
|
||||||
|
self.hBoxLayout = QHBoxLayout(self)
|
||||||
|
self.hBoxLayout.addWidget(self.label, 1, Qt.AlignCenter)
|
||||||
|
self.setObjectName(text.replace(" ", "-"))
|
||||||
|
|
||||||
|
|
||||||
|
class Window(FramelessWindow):
|
||||||
|
## 定义信号:调整高度
|
||||||
|
heightChanged = Signal(int)
|
||||||
|
|
||||||
|
def __init__(self):
|
||||||
|
super().__init__()
|
||||||
|
self.setTitleBar(StandardTitleBar(self))
|
||||||
|
|
||||||
|
# use dark theme mode
|
||||||
|
# setTheme(Theme.DARK)
|
||||||
|
|
||||||
|
# change the theme color
|
||||||
|
# setThemeColor('#0078d4')
|
||||||
|
|
||||||
|
self.hBoxLayout = QHBoxLayout(self)
|
||||||
|
self.navigationInterface = NavigationInterface(self, showMenuButton=True)
|
||||||
|
self.stackWidget = QStackedWidget(self)
|
||||||
|
|
||||||
|
# create sub interface
|
||||||
|
self.system = SystemInterface(self) # 系统设置
|
||||||
|
self.product = ProduceInterface(self)
|
||||||
|
self.robot = Widget("机械臂基础设置", self) # 暂时不用
|
||||||
|
self.io = Widget("IO面板", self) # 需要完成
|
||||||
|
self.position = CoodFormsInterface(self) # 位置设定
|
||||||
|
self.basic = Widget("基础设置", self) # 需要完成
|
||||||
|
self.point = Widget("点位调试", self)
|
||||||
|
self.other = Widget("其他设置", self)
|
||||||
|
self.data = DataInterface(self) # 数据采集
|
||||||
|
|
||||||
|
# initialize layout
|
||||||
|
self.initLayout()
|
||||||
|
|
||||||
|
# add items to navigation interface
|
||||||
|
self.initNavigation()
|
||||||
|
|
||||||
|
self.initWindow()
|
||||||
|
|
||||||
|
def initLayout(self):
|
||||||
|
self.hBoxLayout.setSpacing(0)
|
||||||
|
self.hBoxLayout.setContentsMargins(0, self.titleBar.height(), 0, 0)
|
||||||
|
self.hBoxLayout.addWidget(self.navigationInterface)
|
||||||
|
self.hBoxLayout.addWidget(self.stackWidget)
|
||||||
|
self.hBoxLayout.setStretchFactor(self.stackWidget, 1)
|
||||||
|
|
||||||
|
def initNavigation(self):
|
||||||
|
# enable acrylic effect
|
||||||
|
# self.navigationInterface.setAcrylicEnabled(True)
|
||||||
|
|
||||||
|
# self.addSubInterface 加入导航栏页面
|
||||||
|
self.addSubInterface(
|
||||||
|
self.system, FIF.SETTING, "系统设置", NavigationItemPosition.SCROLL
|
||||||
|
)
|
||||||
|
self.addSubInterface(
|
||||||
|
self.product, FIF.COMPLETED, "生产界面", parent=self.system
|
||||||
|
)
|
||||||
|
self.addSubInterface(
|
||||||
|
self.robot, FIF.ROBOT, "机械臂基础设置", parent=self.system
|
||||||
|
)
|
||||||
|
self.addSubInterface(self.io, FIF.GAME, "IO面板", parent=self.system)
|
||||||
|
self.addSubInterface(self.position, FIF.IOT, "位置设定", parent=self.system)
|
||||||
|
self.addSubInterface(
|
||||||
|
self.basic, FIF.DEVELOPER_TOOLS, "基础设置", parent=self.system
|
||||||
|
)
|
||||||
|
self.addSubInterface(self.point, FIF.MOVE, "点位调试", parent=self.system)
|
||||||
|
|
||||||
|
# self.navigationInterface.addSeparator()
|
||||||
|
self.addSubInterface(
|
||||||
|
self.other, FIF.APPLICATION, "其他设置", NavigationItemPosition.SCROLL
|
||||||
|
)
|
||||||
|
|
||||||
|
self.addSubInterface(
|
||||||
|
self.data, FIF.PHOTO, "数据采集", NavigationItemPosition.SCROLL
|
||||||
|
)
|
||||||
|
# add navigation items to scroll area
|
||||||
|
# for i in range(1, 21):
|
||||||
|
# self.navigationInterface.addItem(
|
||||||
|
# f'folder{i}',
|
||||||
|
# FIF.FOLDER,
|
||||||
|
# f'Folder {i}',
|
||||||
|
# lambda: print('Folder clicked'),
|
||||||
|
# position=NavigationItemPosition.SCROLL
|
||||||
|
# )
|
||||||
|
|
||||||
|
# add custom widget to bottom
|
||||||
|
self.navigationInterface.addWidget(
|
||||||
|
routeKey="avatar",
|
||||||
|
widget=NavigationAvatarWidget("用户设置", "resource/shoko.png"),
|
||||||
|
onClick=self.showMessageBox,
|
||||||
|
position=NavigationItemPosition.BOTTOM,
|
||||||
|
)
|
||||||
|
|
||||||
|
#!IMPORTANT: don't forget to set the default route key if you enable the return button
|
||||||
|
# qrouter.setDefaultRouteKey(self.stackWidget, self.musicInterface.objectName())
|
||||||
|
|
||||||
|
# set the maximum width
|
||||||
|
self.navigationInterface.setExpandWidth(220)
|
||||||
|
|
||||||
|
self.stackWidget.currentChanged.connect(self.onCurrentInterfaceChanged)
|
||||||
|
self.stackWidget.setCurrentIndex(1)
|
||||||
|
|
||||||
|
# always expand
|
||||||
|
self.navigationInterface.setCollapsible(False)
|
||||||
|
|
||||||
|
def initWindow(self):
|
||||||
|
self.resize(900, 700)
|
||||||
|
self.setWindowIcon(QIcon("resource/logo.png"))
|
||||||
|
self.setWindowTitle("密胺投料控制系统")
|
||||||
|
self.titleBar.setAttribute(Qt.WA_StyledBackground)
|
||||||
|
|
||||||
|
desktop = QApplication.screens()[0].availableGeometry()
|
||||||
|
w, h = desktop.width(), desktop.height()
|
||||||
|
self.move(w // 2 - self.width() // 2, h // 2 - self.height() // 2)
|
||||||
|
|
||||||
|
# NOTE: set the minimum window width that allows the navigation panel to be expanded
|
||||||
|
self.navigationInterface.setMinimumExpandWidth(900)
|
||||||
|
self.navigationInterface.expand(useAni=True)
|
||||||
|
|
||||||
|
self.setQss()
|
||||||
|
|
||||||
|
def addSubInterface(
|
||||||
|
self,
|
||||||
|
interface,
|
||||||
|
icon,
|
||||||
|
text: str,
|
||||||
|
position=NavigationItemPosition.TOP,
|
||||||
|
parent=None,
|
||||||
|
):
|
||||||
|
"""add sub interface"""
|
||||||
|
self.stackWidget.addWidget(interface)
|
||||||
|
self.navigationInterface.addItem(
|
||||||
|
routeKey=interface.objectName(),
|
||||||
|
icon=icon,
|
||||||
|
text=text,
|
||||||
|
onClick=lambda: self.switchTo(interface),
|
||||||
|
position=position,
|
||||||
|
tooltip=text,
|
||||||
|
parentRouteKey=parent.objectName() if parent else None,
|
||||||
|
)
|
||||||
|
|
||||||
|
def setQss(self):
|
||||||
|
color = "dark" if isDarkTheme() else "light"
|
||||||
|
with open(f"resource/{color}/demo.qss", encoding="utf-8") as f:
|
||||||
|
self.setStyleSheet(f.read())
|
||||||
|
|
||||||
|
def switchTo(self, widget):
|
||||||
|
self.stackWidget.setCurrentWidget(widget)
|
||||||
|
|
||||||
|
def onCurrentInterfaceChanged(self, index):
|
||||||
|
widget = self.stackWidget.widget(index)
|
||||||
|
self.navigationInterface.setCurrentItem(widget.objectName())
|
||||||
|
|
||||||
|
#!IMPORTANT: This line of code needs to be uncommented if the return button is enabled
|
||||||
|
# qrouter.push(self.stackWidget, widget.objectName())
|
||||||
|
|
||||||
|
def resizeEvent(self, event):
|
||||||
|
super().resizeEvent(event)
|
||||||
|
self.heightChanged.emit(self.height())
|
||||||
|
|
||||||
|
def showMessageBox(self):
|
||||||
|
w = MessageBox(
|
||||||
|
"支持作者🥰",
|
||||||
|
"个人开发不易,如果这个项目帮助到了您,可以考虑请作者喝一瓶快乐水🥤。您的支持就是作者开发和维护项目的动力🚀",
|
||||||
|
self,
|
||||||
|
)
|
||||||
|
w.yesButton.setText("来啦老弟")
|
||||||
|
w.cancelButton.setText("下次一定")
|
||||||
|
|
||||||
|
if w.exec():
|
||||||
|
QDesktopServices.openUrl(QUrl("https://afdian.net/a/zhiyiYo"))
|
||||||
|
|
||||||
|
|
||||||
|
def move_test(pos_list: list):
|
||||||
|
print("移动:", pos_list)
|
||||||
|
|
||||||
|
|
||||||
|
# if __name__ == "__main__":
|
||||||
|
# app = QApplication([])
|
||||||
|
# w = Window()
|
||||||
|
# w.position.formsWidget.form_move_signal.connect(move_test)
|
||||||
|
# w.show()
|
||||||
|
# app.exec()
|
||||||
8
mi_an_main.py
Normal file
8
mi_an_main.py
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
from PySide6.QtWidgets import QApplication
|
||||||
|
from app.controller.mi_an.main_controller import MainController
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
app = QApplication([])
|
||||||
|
controller = MainController()
|
||||||
|
controller.showMainWindow()
|
||||||
|
app.exec()
|
||||||
Reference in New Issue
Block a user