修复筛选BUG 优化表格按钮类

main
zcwBit 3 months ago
parent 4003e69ecd
commit cf88a2c37d

@ -11,6 +11,7 @@ QComboBox, QStyledItemDelegate, QVBoxLayout, QSplitter
from UI.ProfibusWidgets.LoadingDataWidget import LoadingDataWidget
from UI.ProfibusWidgets.ObjectTypeEditlayout import ObjectTypeEditlayout
from UI.VarManages.BaseButtonDelegate import BaseButtonDelegate
from utils import Globals
@ -147,10 +148,10 @@ class VarTableModel(QAbstractTableModel):
class VarButtonDelegate(QItemDelegate):
class ProfibusButtonDelegate(BaseButtonDelegate):
"""该类用于向单元格中添加按钮 任务表格"""
def __init__(self, parent=None):
super(VarButtonDelegate, self).__init__(parent)
super(ProfibusButtonDelegate, self).__init__(parent)
def paint(self, painter, option, index):
if not self.parent().indexWidget(index):
@ -239,9 +240,15 @@ class VarButtonDelegate(QItemDelegate):
sender = self.sender()
blockView = self.parent()
model = blockView.model
# 使用基类的验证方法获取行索引
view_row, source_row = self._validate_button_indices(sender)
if view_row is None:
return
blockType = blockView.blockType
blockIndex = blockView.blcokIndex
parmIndex = model.datas[sender.index[0]][1]
parmIndex = model.datas[source_row][1]
blockManage = Globals.getValue('blockManage')
values = []
#修改单位
@ -261,7 +268,7 @@ class VarButtonDelegate(QItemDelegate):
values = objectTypeEditlayout.getEditlineValue()
dataType = model.datas[sender.index[0]][4]
dataType = model.datas[source_row][4]
if not values:
reply = QMessageBox.question(self.parent(),
'警告',
@ -286,7 +293,13 @@ class VarButtonDelegate(QItemDelegate):
sender = self.sender()
blockView = self.parent()
model = blockView.model
parmIndex = model.datas[sender.index[0]][1]
# 使用基类的验证方法获取行索引
view_row, source_row = self._validate_button_indices(sender)
if view_row is None:
return
parmIndex = model.datas[source_row][1]
blockType = blockView.blockType
blockIndex = blockView.blcokIndex
# print(blockName, blcokIndex, index)
@ -297,7 +310,7 @@ class VarButtonDelegate(QItemDelegate):
# self.loadingDataWidget.loadData(1, 1)
self.loadingDataWidget = LoadingDataWidget(refreshType = True)
self.loadingDataWidget.exec_()
model.updateColumn(sender.index[0], value)
model.updateColumn(source_row, value)
# self.parent().resizeHeader()
blockView.proxy.invalidate()

@ -2,7 +2,7 @@ from PyQt5 import QtCore
from PyQt5.QtGui import QTextDocument
from PyQt5.QtCore import Qt
from PyQt5.QtWidgets import QHeaderView, QAbstractItemView, QTableView, QWidget, QDesktopWidget
from UI.ProfibusWidgets.BlockParameterModel import VarTableModel, VarButtonDelegate
from UI.ProfibusWidgets.BlockParameterModel import VarTableModel, ProfibusButtonDelegate
from utils.DBModels.DeviceParModels import *
@ -49,7 +49,7 @@ class ParmView(QTableView):
self.setData()
def setHeader(self):
self.setItemDelegateForColumn(7, VarButtonDelegate(self))
self.setItemDelegateForColumn(7, ProfibusButtonDelegate(self))
# self.setItemDelegateForColumn(5, ComboBoxDelegate(self))
self.model = VarTableModel(['序号','索引', '参数名', '描述', '数据类型', '访问', '当前值', '输入值'], [], table = self)

@ -112,7 +112,13 @@ class AnalogButtonDelegate(TcRtdButtonDelegate):
def trend_action(self):
sender = self.sender()
model = self.parent().model
varName = model.datas[sender.index[0]][3]
# 使用基类的验证方法获取行索引
view_row, source_row = self._validate_button_indices(sender)
if view_row is None:
return
varName = model.datas[source_row][3]
# 以变量名为key避免重复打开
if varName not in self.trendWindows or self.trendWindows[varName] is None:
self.trendWindows[varName] = ActualTrend(varName=varName)
@ -123,13 +129,19 @@ class AnalogButtonDelegate(TcRtdButtonDelegate):
def edit_action(self):
sender = self.sender()
model = self.parent().model
# 使用基类的验证方法获取行索引
view_row, source_row = self._validate_button_indices(sender)
if view_row is None:
return
if sender.isEdit:
sender.setIcon(qtawesome.icon('fa.save', color='#1fbb6f'))
sender.isEdit = False
sender.oldName = model.datas[sender.index[0]][3]
model.editableList.append(sender.index[0])
sender.oldName = model.datas[source_row][3]
model.editableList.append(source_row)
else:
varMes = model.datas[sender.index[0]]
varMes = model.datas[source_row]
name,channelNumber, des, varType, min, max = str(varMes[3]), str(varMes[4]), str(varMes[5]),str(varMes[6]), str(varMes[7]), str(varMes[8])
if not name or not varType:
reply = QMessageBox.question(self.parent(),
@ -138,7 +150,7 @@ class AnalogButtonDelegate(TcRtdButtonDelegate):
QMessageBox.Yes)
return
sender.isEdit = True
model.editableList.remove(sender.index[0])
model.editableList.remove(source_row)
if sender.oldName:
if sender.oldName == name:
AnalogManage.editVar(name=sender.oldName, Nname=name, channelNumber = channelNumber,
@ -159,24 +171,30 @@ class AnalogButtonDelegate(TcRtdButtonDelegate):
des=des, varType=varType, min=min, max=max)
sender.setIcon(qtawesome.icon('fa.pencil', color='#4c8cf2'))
rowIndex = sender.index[0]
varMes = AnalogManage.getByName(name)
varMes.insert(1, '')
varMes.insert(2, '')
varMes.append('')
model.insert_data(varMes, rowIndex)
model.remove_row(rowIndex + 1)
model.insert_data(varMes, source_row)
model.remove_row(source_row + 1)
def start_action(self):
sender = self.sender()
model = self.parent().model
value = model.datas[sender.index[0]][1]
varType = model.datas[sender.index[0]][6]
min = model.datas[sender.index[0]][7]
max = model.datas[sender.index[0]][8]
# print(model.datas[sender.index[0]][9])
# 使用基类的验证方法获取行索引
view_row, source_row = self._validate_button_indices(sender)
if view_row is None:
return
# 获取强制值(从视图)和其他数据(从源模型)
value = self._get_view_data(view_row, 1) # 强制值列
varType = model.datas[source_row][6]
min = model.datas[source_row][7]
max = model.datas[source_row][8]
# print(model.datas[source_row][9])
pattern = re.compile(r'[^0-9\.-]+')
if varType in ['AI', 'DI'] and model.datas[sender.index[0]][9] != '模拟值':
if varType in ['AI', 'DI'] and model.datas[source_row][9] != '模拟值':
reply = QMessageBox.question(self.parent(),
'警告',
"AI,DI类型变量不允许强制值",
@ -188,14 +206,14 @@ class AnalogButtonDelegate(TcRtdButtonDelegate):
"请输入强制值或数字",
QMessageBox.Yes)
return
if sender.index[0] > 15:
if source_row > 15:
if not value.isdigit:
reply = QMessageBox.question(self.parent(),
'警告',
"请输入0或1",
QMessageBox.Yes)
return
if min and max and sender.index[0] < 16:
if min and max and source_row < 16:
if float(value) < float(min) or float(value) > float(max):
reply = QMessageBox.question(self.parent(),
'警告',
@ -205,29 +223,30 @@ class AnalogButtonDelegate(TcRtdButtonDelegate):
else:
min = None
max = None
# print(value, sender.index[0])
if (float(value) > 20 or float(value)) < 4 and sender.index[0] < 8:
# print(value, source_row)
if (float(value) > 20 or float(value)) < 4 and source_row < 8:
reply = QMessageBox.question(self.parent(),
'警告',
"超出量程范围1",
QMessageBox.Yes)
return
if float(value) > 10000 or float(value) < 0.1 and 8 < sender.index[0] < 16:
if float(value) > 10000 or float(value) < 0.1 and 8 < source_row < 16:
reply = QMessageBox.question(self.parent(),
'警告',
"超出量程范围2",
QMessageBox.Yes)
return
# if sender.index[0] < 8:
# model.table.realList[sender.index[0]] = getRealAO(float(value), max, min)
# model.table.valueList[sender.index[0]] = float(value)
# if source_row < 8:
# model.table.realList[source_row] = getRealAO(float(value), max, min)
# model.table.valueList[source_row] = float(value)
# else:
# model.table.realList[sender.index[0]] = float(value)
# model.table.valueList[sender.index[0]] = float(value)
res = Globals.getValue('protocolManage').writeVariableValue(model.datas[sender.index[0]][3], float(value))
# model.table.realList[source_row] = float(value)
# model.table.valueList[source_row] = float(value)
# print(model.datas[source_row][3])
res = Globals.getValue('protocolManage').writeVariableValue(model.datas[source_row][3], float(value))
if res:
forceVars = Globals.getValue('forceVars')
forceVars.add(model.datas[sender.index[0]][3])
forceVars.add(model.datas[source_row][3])
Globals.setValue('forceVars', forceVars)
else:
QMessageBox.information(self.parent(), '提示', '写入失败', QMessageBox.Yes)

@ -0,0 +1,79 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
基础按钮委托类
提供通用的按钮索引获取和数据访问方法
"""
from PyQt5.QtWidgets import QItemDelegate, QMessageBox
from PyQt5.QtCore import Qt
class BaseButtonDelegate(QItemDelegate):
"""基础按钮委托类,提供通用的索引处理方法"""
def __init__(self, parent=None):
super(BaseButtonDelegate, self).__init__(parent)
def _get_button_row_indices(self, button):
"""
获取按钮所在的视图行和源模型行索引
返回: (view_row, source_row) (None, None) 如果找不到
"""
table_view = self.parent()
# 获取操作列索引(最后一列)
if hasattr(table_view, 'proxy') and table_view.proxy:
operation_col = table_view.proxy.columnCount() - 1
row_count = table_view.proxy.rowCount()
else:
operation_col = table_view.model.columnCount() - 1
row_count = table_view.model.rowCount()
# 查找按钮所在的行
for row in range(row_count):
if hasattr(table_view, 'proxy') and table_view.proxy:
index = table_view.proxy.index(row, operation_col)
else:
index = table_view.model.index(row, operation_col)
widget = table_view.indexWidget(index)
if widget and widget.layout():
for i in range(widget.layout().count()):
if widget.layout().itemAt(i).widget() == button:
view_row = row
# 转换为源模型索引
if hasattr(table_view, 'proxy') and table_view.proxy:
proxy_index = table_view.proxy.index(view_row, 0)
source_index = table_view.proxy.mapToSource(proxy_index)
source_row = source_index.row()
else:
source_row = view_row
return view_row, source_row
return None, None
def _get_view_data(self, view_row, column):
"""
从视图中获取指定行列的数据
"""
table_view = self.parent()
if hasattr(table_view, 'proxy') and table_view.proxy:
index = table_view.proxy.index(view_row, column)
return table_view.proxy.data(index, Qt.DisplayRole)
else:
return table_view.model.datas[view_row][column]
def _validate_button_indices(self, button):
"""
验证并获取按钮索引如果失败则显示错误消息
返回: (view_row, source_row) (None, None)
"""
view_row, source_row = self._get_button_row_indices(button)
if view_row is None:
QMessageBox.warning(self.parent(), '错误', '无法确定按钮所在行', QMessageBox.Yes)
return None, None
return view_row, source_row

@ -5,7 +5,7 @@ from PyQt5.QtWidgets import QHBoxLayout, QWidget, QMessageBox
from model.ProjectModel.VarManage import *
from UI.VarManages.ModbusModel import *
from utils import Globals
from UI.VarManages.BaseButtonDelegate import BaseButtonDelegate
class HartModel(VarTableModel):
def __init__(self, header, data: list, table = None):
@ -86,7 +86,7 @@ class HartModel(VarTableModel):
return Qt.ItemIsEnabled
class HartButtonDelegate(VarButtonDelegate):
class HartButtonDelegate(BaseButtonDelegate):
"""该类用于向单元格中添加按钮 任务表格"""
def __init__(self, parent=None):
@ -128,13 +128,19 @@ class HartButtonDelegate(VarButtonDelegate):
def edit_action(self):
sender = self.sender()
model = self.parent().model
# 使用基类的验证方法获取行索引
view_row, source_row = self._validate_button_indices(sender)
if view_row is None:
return
if sender.isEdit:
sender.setIcon(qtawesome.icon('fa.save', color='#1fbb6f'))
sender.isEdit = False
sender.oldName = model.datas[sender.index[0]][1]
model.editableList.append(sender.index[0])
sender.oldName = model.datas[source_row][1]
model.editableList.append(source_row)
else:
varMes = model.datas[sender.index[0]]
varMes = model.datas[source_row]
name, des = str(varMes[1]), str(varMes[2])
if not name :
reply = QMessageBox.question(self.parent(),
@ -143,13 +149,12 @@ class HartButtonDelegate(VarButtonDelegate):
QMessageBox.Yes)
return
sender.isEdit = True
model.editableList.remove(sender.index[0])
model.editableList.remove(source_row)
if sender.oldName:
HartVarManage.editVar(name = sender.oldName, Nname = name, des = des)
else:
HartVarManage.createVar(varName = name, des = des)
sender.setIcon(qtawesome.icon('fa.pencil', color='#4c8cf2'))
rowIndex = sender.index[0]
varMes = HartVarManage.getByName(name)
model.insert_data(varMes, rowIndex)
model.remove_row(rowIndex + 1)
model.insert_data(varMes, source_row)
model.remove_row(source_row + 1)

@ -4,6 +4,7 @@ from PyQt5.QtCore import Qt, QVariant, QSize
from PyQt5.QtWidgets import QHBoxLayout, QWidget, QMessageBox, QComboBox
from model.ProjectModel.VarManage import *
from UI.VarManages.ModbusModel import *
from UI.VarManages.BaseButtonDelegate import BaseButtonDelegate
from utils import Globals
import re
@ -75,7 +76,7 @@ class HartSimulateModel(VarTableModel):
return Qt.ItemIsEnabled
class HartSimulateButtonDelegate(VarButtonDelegate):
class HartSimulateButtonDelegate(BaseButtonDelegate):
"""该类用于向单元格中添加按钮 任务表格"""
def __init__(self, parent=None):
@ -128,13 +129,19 @@ class HartSimulateButtonDelegate(VarButtonDelegate):
def edit_action(self):
sender = self.sender()
model = self.parent().model
# 使用基类的验证方法获取行索引
view_row, source_row = self._validate_button_indices(sender)
if view_row is None:
return
if sender.isEdit:
sender.setIcon(qtawesome.icon('fa.save', color='#1fbb6f'))
sender.isEdit = False
sender.oldName = model.datas[sender.index[0]][1]
model.editableList.append(sender.index[0])
sender.oldName = model.datas[source_row][1]
model.editableList.append(source_row)
else:
varMes = model.datas[sender.index[0]]
varMes = model.datas[source_row]
name, des = str(varMes[1]), str(varMes[2])
# print(name, des)
if not name :
@ -144,24 +151,30 @@ class HartSimulateButtonDelegate(VarButtonDelegate):
QMessageBox.Yes)
return
sender.isEdit = True
model.editableList.remove(sender.index[0])
model.editableList.remove(source_row)
if sender.oldName:
HartSimulateVarManage.editVar(name = sender.oldName, Nname = name, des = des)
else:
HartSimulateVarManage.createVar(varName = name, des = des)
sender.setIcon(qtawesome.icon('fa.pencil', color='#4c8cf2'))
rowIndex = sender.index[0]
varMes = HartSimulateVarManage.getByName(name)
model.insert_data(varMes, rowIndex)
model.remove_row(rowIndex + 1)
model.insert_data(varMes, source_row)
model.remove_row(source_row + 1)
def start_action(self):
sender = self.sender()
model = self.parent().model
value1 = model.datas[sender.index[0]][3]
minSpan = model.datas[sender.index[0]][7]
maxSpan = model.datas[sender.index[0]][8]
writeList = [str(x) for x in model.datas[sender.index[0]][3:9]]
# 使用基类的验证方法获取行索引
view_row, source_row = self._validate_button_indices(sender)
if view_row is None:
return
# 获取强制值(从视图)和其他数据(从源模型)
value1 = self._get_view_data(view_row, 3) # 强制值列
minSpan = model.datas[source_row][7]
maxSpan = model.datas[source_row][8]
writeList = [str(x) for x in model.datas[source_row][3:9]]
pattern = re.compile(r'[^0-9\.-]+')
if minSpan and maxSpan and value1 and not re.findall(pattern, str(value1) + str(minSpan) + str(maxSpan)):
if float(value1) < float(minSpan) or float(value1) > float(maxSpan):
@ -188,5 +201,5 @@ class HartSimulateButtonDelegate(VarButtonDelegate):
return
forceVars = Globals.getValue('forceVars')
forceVars.add(model.datas[sender.index[0]][1])
forceVars.add(model.datas[source_row][1])
Globals.setValue('forceVars', forceVars)

@ -9,6 +9,7 @@ from PyQt5 import QtGui,QtCore,QtWidgets
from PyQt5.QtCore import QAbstractTableModel, QModelIndex, Qt, QVariant, QSize
from PyQt5.QtWidgets import QItemDelegate, QHBoxLayout, QWidget, QMessageBox, QComboBox, QStyleOptionViewItem
from UI.VarManages.BaseButtonDelegate import BaseButtonDelegate
from sympy import N
@ -204,12 +205,12 @@ class VarTableModel(QAbstractTableModel):
class VarButtonDelegate(QItemDelegate):
class ModbusButtonDelegate(BaseButtonDelegate):
"""该类用于向单元格中添加按钮 任务表格"""
trendWidgetDict = {}
def __init__(self, parent=None):
super(VarButtonDelegate, self).__init__(parent)
super(ModbusButtonDelegate, self).__init__(parent)
def trendWidget(self, varName):
if varName not in self.trendWidgetDict:
@ -310,8 +311,16 @@ class VarButtonDelegate(QItemDelegate):
def start_action(self):
sender = self.sender()
model = self.parent().model
varMes = model.datas[sender.index[0]]
value, name, des, varType, slaveID, address, min, max, order = str(varMes[1]), str(varMes[3]), str(varMes[4]), str(varMes[5]), str(varMes[6]), str(varMes[7]), str(varMes[8]), str(varMes[9]), str(varMes[10])
# 使用基类的验证方法获取行索引
view_row, source_row = self._validate_button_indices(sender)
if view_row is None:
return
# 获取强制值(从视图)和其他数据(从源模型)
value = str(self._get_view_data(view_row, 1)) # 强制值列
varMes = model.datas[source_row]
name, des, varType, slaveID, address, min, max, order = str(varMes[3]), str(varMes[4]), str(varMes[5]), str(varMes[6]), str(varMes[7]), str(varMes[8]), str(varMes[9]), str(varMes[10])
pattern = re.compile(r'[^0-9\.-]+')
if not value or re.findall(pattern, str(value)):
reply = QMessageBox.question(self.parent(),
@ -363,22 +372,27 @@ class VarButtonDelegate(QItemDelegate):
sender = self.sender()
model = self.parent().model
modbusType = self.parent().modbusType
fucationCbRow = str('cb' + str(sender.index[0]) + str(5))
fucationIndex = self.parent().model.index(sender.index[0], 5)
# 使用基类的验证方法获取行索引
view_row, source_row = self._validate_button_indices(sender)
if view_row is None:
return
fucationCbRow = str('cb' + str(source_row) + str(5))
fucationIndex = self.parent().model.index(source_row, 5)
fucationDelegate = self.parent().itemDelegate(fucationIndex)
fucationCheckbox = getattr(fucationDelegate, fucationCbRow)
if sender.isEdit:
sender.setIcon(qtawesome.icon('fa.save', color='#1fbb6f'))
sender.isEdit = False
sender.oldName = model.datas[sender.index[0]][3]
model.editableList.append(sender.index[0])
sender.oldName = model.datas[source_row][3]
model.editableList.append(source_row)
fucationCheckbox.setEnabled(True)
self.parent().viewport().update()
else:
varMes = model.datas[sender.index[0]]
varMes = model.datas[source_row]
name, des, varType, slaveID, address, min, max, varModel, order = str(varMes[3]), str(varMes[4]), str(varMes[5]), str(varMes[6]), str(varMes[7]), str(varMes[8]), str(varMes[9]), str(varMes[-2]), str(varMes[-1])
if varType == '':
varType = 0
@ -419,36 +433,47 @@ class VarButtonDelegate(QItemDelegate):
sender.setIcon(qtawesome.icon('fa.pencil', color='#4c8cf2'))
rowIndex = sender.index[0]
varMes = ModbusVarManage.getByName(name, modbusType)
varMes.append('本地值')
varMes.append('int')
varMes.insert(1, '')
varMes.insert(2, '')
model.insert_data(varMes, rowIndex)
model.remove_row(rowIndex + 1)
model.insert_data(varMes, source_row)
model.remove_row(source_row + 1)
sender.isEdit = True
fucationCheckbox.setEnabled(False)
# varModelCheckbox.setEnabled(False)
model.editableList.remove(sender.index[0])
model.editableList.remove(source_row)
self.parent().viewport().update()
def delete_action(self):
sender = self.sender()
model = self.parent().model
name = str(model.datas[sender.index[0]][3])
# 使用基类的验证方法获取行索引
view_row, source_row = self._validate_button_indices(sender)
if view_row is None:
return
name = str(model.datas[source_row][3])
modbusType = self.parent().modbusType
if sender.editButton.isEdit:
ModbusVarManage.deleteVar(name = name, modbusType = modbusType)
model.remove_row(sender.index[0])
model.remove_row(source_row)
def trend_action(self):
model = self.parent().model
if model.table.parent._isPopenOpen:
sender = self.sender()
name = str(model.datas[sender.index[0]][3])
# 使用基类的验证方法获取行索引
view_row, source_row = self._validate_button_indices(sender)
if view_row is None:
return
name = str(model.datas[source_row][3])
trend = self.trendWidget(varName = name)
trend.show()

@ -89,8 +89,9 @@ class RpcVarModel(QAbstractTableModel):
return Qt.ItemIsEnabled
from PyQt5.QtWidgets import QStyledItemDelegate, QPushButton, QStyleOptionButton, QStyle, QApplication
from UI.VarManages.BaseButtonDelegate import BaseButtonDelegate
class RpcVarButtonDelegate(QStyledItemDelegate):
class RpcVarButtonDelegate(BaseButtonDelegate):
def __init__(self, parent=None):
super(RpcVarButtonDelegate, self).__init__(parent)
@ -116,11 +117,16 @@ class RpcVarButtonDelegate(QStyledItemDelegate):
def force_action(self, sender):
model = self.parent().model
row = sender.index[0]
varName = model.datas[row][2]
minValue = model.datas[row][4]
maxValue = model.datas[row][5]
forceValue = model.inputValues.get(row, '')
# 使用基类的验证方法获取行索引
view_row, source_row = self._validate_button_indices(sender)
if view_row is None:
return
varName = model.datas[source_row][2]
minValue = model.datas[source_row][4]
maxValue = model.datas[source_row][5]
forceValue = model.inputValues.get(source_row, '')
if forceValue == '':
QMessageBox.warning(self.parent(), '提示', '请先输入强制值')
return

@ -6,6 +6,7 @@ from PyQt5.QtWidgets import QHBoxLayout, QWidget, QMessageBox, QComboBox
from protocol.TCP.TemToMv import temToMv
from model.ProjectModel.VarManage import *
from UI.VarManages.ModbusModel import *
from UI.VarManages.BaseButtonDelegate import BaseButtonDelegate
from UI.TrendManage.ActualTrendWidget import ActualTrend
from utils import Globals
import re
@ -105,7 +106,7 @@ class TcRtdModel(VarTableModel):
class TcRtdButtonDelegate(VarButtonDelegate):
class TcRtdButtonDelegate(BaseButtonDelegate):
"""该类用于向单元格中添加按钮 任务表格"""
def __init__(self, parent=None):
@ -173,12 +174,20 @@ class TcRtdButtonDelegate(VarButtonDelegate):
def start_action(self):
sender = self.sender()
model = self.parent().model
value = model.datas[sender.index[0]][1]
varType = model.datas[sender.index[0]][6]
min = model.datas[sender.index[0]][7]
max = model.datas[sender.index[0]][8]
compensation = model.datas[sender.index[0]][9]
# 使用基类的验证方法获取行索引
view_row, source_row = self._validate_button_indices(sender)
if view_row is None:
return
# 获取强制值(从视图)和其他数据(从源模型)
value = self._get_view_data(view_row, 1) # 强制值列
varType = model.datas[source_row][6]
min = model.datas[source_row][7]
max = model.datas[source_row][8]
compensation = model.datas[source_row][9]
pattern = re.compile(r'[^0-9\.-]+')
print(model.datas[source_row][3])
if not value or re.findall(pattern, str(value) + str(compensation)):
reply = QMessageBox.question(self.parent(),
'警告',
@ -216,13 +225,13 @@ class TcRtdButtonDelegate(VarButtonDelegate):
# 直接写入变量值
res = Globals.getValue('protocolManage').writeVariableValue(
model.datas[sender.index[0]][3],
model.datas[source_row][3],
float(value)
)
if res:
forceVars = Globals.getValue('forceVars')
forceVars.add(model.datas[sender.index[0]][3])
forceVars.add(model.datas[source_row][3])
Globals.setValue('forceVars', forceVars)
else:
QMessageBox.information(self.parent(), '提示', '写入失败', QMessageBox.Yes)
@ -230,13 +239,19 @@ class TcRtdButtonDelegate(VarButtonDelegate):
def edit_action(self):
sender = self.sender()
model = self.parent().model
# 使用基类的验证方法获取行索引
view_row, source_row = self._validate_button_indices(sender)
if view_row is None:
return
if sender.isEdit:
sender.setIcon(qtawesome.icon('fa.save', color='#1fbb6f'))
sender.isEdit = False
sender.oldName = model.datas[sender.index[0]][3]
model.editableList.append(sender.index[0])
sender.oldName = model.datas[source_row][3]
model.editableList.append(source_row)
else:
varMes = model.datas[sender.index[0]]
varMes = model.datas[source_row]
name, channelNumber, des, varType, min, max, compensationVar = str(varMes[3]), str(varMes[4]), str(varMes[5]),str(varMes[6]), str(varMes[7]), str(varMes[8]), str(varMes[9])
if not name or not varType:
reply = QMessageBox.question(self.parent(),
@ -245,7 +260,7 @@ class TcRtdButtonDelegate(VarButtonDelegate):
QMessageBox.Yes)
return
sender.isEdit = True
model.editableList.remove(sender.index[0])
model.editableList.remove(source_row)
if sender.oldName:
if sender.oldName == name:
TcRtdManage.editVar(name=sender.oldName, Nname=name, channelNumber = channelNumber, des=des,
@ -267,18 +282,23 @@ class TcRtdButtonDelegate(VarButtonDelegate):
min=min, max=max, compensationVar = compensationVar)
sender.setIcon(qtawesome.icon('fa.pencil', color='#4c8cf2'))
rowIndex = sender.index[0]
varMes = TcRtdManage.getByName(name)
varMes.insert(1, '')
varMes.insert(2, '')
varMes.append('')
model.insert_data(varMes, rowIndex)
model.remove_row(rowIndex + 1)
model.insert_data(varMes, source_row)
model.remove_row(source_row + 1)
def trend_action(self):
sender = self.sender()
model = self.parent().model
varName = model.datas[sender.index[0]][3]
# 使用基类的验证方法获取行索引
view_row, source_row = self._validate_button_indices(sender)
if view_row is None:
return
varName = model.datas[source_row][3]
# 以变量名为key避免重复打开
if varName not in self.trendWindows or self.trendWindows[varName] is None:
self.trendWindows[varName] = ActualTrend(varName=varName)

@ -80,7 +80,7 @@ class VarTableView(QTableView):
def setHeader(self):
self.setItemDelegateForColumn(11, VarButtonDelegate(self))
self.setItemDelegateForColumn(11, ModbusButtonDelegate(self))
self.setItemDelegateForColumn(5, ModbusTypeBox(self))
self.setItemDelegateForColumn(10, ModbusVarModelBox(self))
self.model = VarTableModel(['ID', '强制值', '当前值', '变量名', '变量描述', '变量类型',

@ -71,7 +71,7 @@ class VarWidgets(QtWidgets.QWidget):
self.timer = QTimer(self)
# 将定时器超时信号与槽函数showTime()连接
self.timer.timeout.connect(self.proxy.invalidate)
self.timer.start(50) # 启动timer
self.timer.start(500) # 启动timer
Globals.setValue(str(self.modbusType) + 'Table', self.varView)

@ -51,8 +51,8 @@ class ModbusManager:
"""启动 Modbus TCP 主站"""
try:
if self.modbusTcpMaster is not None:
return True
self.modbusTcpMaster.master.close()
self.modbusTcpMaster = None
# 从数据库获取TCP设置
tcpSettings = self._getTcpSettings('master')
if not tcpSettings:
@ -93,8 +93,8 @@ class ModbusManager:
"""启动 Modbus RTU 主站"""
try:
if self.modbusRtuMaster is not None:
return True
self.modbusRtuMaster.master.close()
self.modbusRtuMaster = None
# 从数据库获取RTU设置
rtuSettings = self._getRtuSettings('master')
if not rtuSettings:
@ -136,8 +136,9 @@ class ModbusManager:
"""启动 Modbus TCP 从站"""
try:
if self.modbusTcpSlave is not None:
return True
self.modbusTcpSlave.server.close()
self.modbusTcpSlave = None
# 从数据库获取TCP设置
tcpSettings = self._getTcpSettings('slave')
if not tcpSettings:
@ -150,7 +151,7 @@ class ModbusManager:
)
# 添加默认从站ID
self.modbusTcpSlave.addSlave(1)
# self.modbusTcpSlave.addSlave(1)
return True
@ -177,10 +178,12 @@ class ModbusManager:
"""启动 Modbus RTU 从站"""
try:
if self.modbusRtuSlave is not None:
return True
self.modbusRtuSlave.server.close()
self.modbusRtuSlave = None
# 从数据库获取RTU设置
rtuSettings = self._getRtuSettings('slave')
if not rtuSettings:
return False
@ -197,7 +200,7 @@ class ModbusManager:
self.modbusRtuSlave.start()
# 添加默认从站ID
self.modbusRtuSlave.addSlave(1)
# self.modbusRtuSlave.addSlave(1)
return True
@ -309,40 +312,7 @@ class ModbusManager:
except Exception as e:
print(f"写入RTU从站变量失败: {str(e)}")
return False
def readModbusTcpMasterValue(self, info):
"""读取TCP主站变量值"""
try:
if self.modbusTcpMaster is None:
return None
slaveId = int(info['slaveID'])
address = int(info['address'])
varType = int(info['varType'])
order = info['order']
return self._readModbusValue(self.modbusTcpMaster, slaveId, address, varType, order)
except Exception as e:
print(f"读取TCP主站变量失败: {str(e)}")
return None
def readModbusRtuMasterValue(self, info):
"""读取RTU主站变量值"""
try:
if self.modbusRtuMaster is None:
return None
slaveId = int(info['slaveID'])
address = int(info['address'])
varType = int(info['varType'])
order = info['order']
return self._readModbusValue(self.modbusRtuMaster, slaveId, address, varType, order)
except Exception as e:
print(f"读取RTU主站变量失败: {str(e)}")
return None
def readModbusTcpSlaveValue(self, info):
"""读取TCP从站变量值"""
@ -509,6 +479,7 @@ class ModbusManager:
if value != 'error' and self.variableValueCache is not None and self.cacheLock is not None:
with self.cacheLock:
self.variableValueCache[varName] = value
print(varName, value)
except Exception as e:
print(f"读取TCP主站变量失败 {varName}: {str(e)}")

@ -69,7 +69,11 @@ class RTUSlave():
def readValue(self, slaveId, name, address, order = 'int'):
try:
slave = self.server.get_slave(slaveId)
try:
slave = self.server.get_slave(slaveId)
except Exception as e:
if type(e) == MissingKeyError:
self.addSlave(slaveId)
if order == 'int':
value = slave.get_values(name, address, 1)[0]
else:
@ -86,7 +90,6 @@ class RTUSlave():
value = ABCDToFloat(value)
return value
except Exception as e:
print(e)
return 'error'

@ -2,6 +2,7 @@
import modbus_tk
import modbus_tk.defines as cst
from modbus_tk import modbus_tcp, hooks
from modbus_tk.exceptions import *
import serial
import struct
from .ByteOrder import *
@ -80,7 +81,11 @@ class TCPSlave():
def readValue(self, slaveId, name, address, order = 'int'):
try:
slave = self.server.get_slave(slaveId)
try:
slave = self.server.get_slave(slaveId)
except Exception as e:
if type(e) == MissingKeyError:
self.addSlave(slaveId)
if order == 'int':
value = slave.get_values(name, address, 1)[0]
else:
@ -95,6 +100,7 @@ class TCPSlave():
value = CDABToFloat(value)
return value
except Exception as e:
return 'error'

@ -35,7 +35,7 @@ class ProtocolManage(object):
# Modbus 管理器
self.modbusManager = ModbusManager()
self.modbusManager.setVariableCache(self.variableValueCache, None, self.varInfoCache)
# self.modbusManager.setVariableCache(self.variableValueCache, None, self.varInfoCache)
self.refreshVarCache()
self.cacheLock = threading.Lock()
@ -238,12 +238,12 @@ class ProtocolManage(object):
info = varInfo['variableData']
try:
# 拆分为独立的协议条件判断
if modelType == 'ModbusTcpMasterVar':
value = self.modbusManager.readModbusTcpMasterValue(info)
elif modelType == 'ModbusTcpSlaveVar':
# if modelType == 'ModbusTcpMasterVar':
# value = self.modbusManager.readModbusTcpMasterValue(info)
if modelType == 'ModbusTcpSlaveVar':
value = self.modbusManager.readModbusTcpSlaveValue(info)
elif modelType == 'ModbusRtuMasterVar':
value = self.modbusManager.readModbusRtuMasterValue(info)
# elif modelType == 'ModbusRtuMasterVar':
# value = self.modbusManager.readModbusRtuMasterValue(info)
elif modelType == 'ModbusRtuSlaveVar':
value = self.modbusManager.readModbusRtuSlaveValue(info)
elif modelType == 'HartVar':

Loading…
Cancel
Save