import re import qtawesome from PyQt5.QtGui import QPixmap, QPainter, QIcon from PyQt5.QtCore import Qt from PyQt5.QtWidgets import QStyledItemDelegate, QStyle, QComboBox, QMessageBox, QPushButton,QStackedWidget, QLineEdit \ , QVBoxLayout, QHBoxLayout, QWidget, QLabel, QSplitter, QButtonGroup, QDialog, QRadioButton from utils.DBModels.DeviceParModels import * from UI.BlockParameterView import ParmView from UI.SearchAddressWidget import SearchAddressWidget from utils.DBModels.DeviceParModels import * from utils import Globals from UI.LoadingDataWidget import LoadingDataWidget from UI.EditAddressWidget import EditAddressWidget from model.ProjectModel.BlockManage import BlockManage, BlockType, TBType class ShowImage(QWidget): def __init__(self, image_path): super().__init__() self.image_path = image_path self.pixmap = QPixmap(self.image_path) def paintEvent(self, event): painter = QPainter(self) painter.drawPixmap(self.rect(), self.pixmap) class HideTextDelegate(QStyledItemDelegate): def paint(self, painter, option, index): # 仅在下拉列表中绘制文本,避免在ComboBox显示区域绘制 if option.state & QStyle.State_Enabled: super().paint(painter, option, index) def sizeHint(self, option, index): # 返回原始大小,确保下拉列表项不受ComboBox宽度影响 return super().sizeHint(option, index) class TbCombox(QComboBox): def __init__(self): super().__init__() # self.tbType = tbType self.initUI() def initUI(self): # 创建ComboBox self.addItems(["压力转换块", "温度转换块", "物位转换块", "流量转换块", 'WIKA液位计']) self.setEditable(True) # 设置为可编辑以应用样式表隐藏文本 self.setObjectName('tbcombox') # 设置样式隐藏文本 self.lineEdit().setStyleSheet("color: transparent; border:none; background-color: #f0f0f0") self.lineEdit().setCursor(Qt.ArrowCursor) self.lineEdit().setReadOnly(True) # 设置自定义代理以调整下拉列表行为 self.delegate = HideTextDelegate(self) self.setItemDelegate(self.delegate) # 设置ComboBox的固定大小 self.setFixedSize(30, 40) # 确保下拉列表宽度适应最长项 # max_width = max(self.fontMetrics().width(self.itemText(i)) for i in range(self.count())) self.view().setMinimumWidth(130) class DynamicAddBlock(QHBoxLayout): def __init__(self, blocklist, TbtypeList): super().__init__() self.blocklist = blocklist self.buttonlist = [] self.blockViewlist = [] self.tbtypeList = TbtypeList #存放转换块的各种类型 # print(self.tbtypeList) self.tbList = ['PressureTranslationBlock', 'TemperatureTranslationBlock', 'LevelTranslationBlock', 'FlowTranslationBlock', 'WiKaLevelTranslationBlock'] #存放四个转换块 self.enumList = [TBType.pressureTB, TBType.tempTB, TBType.levelTB, TBType.flowTB, TBType.wikaLevelTB] self.initUI() def initUI(self): pbNumber = self.blocklist[0] tbNumber = self.blocklist[1] fbNumber = self.blocklist[2] for i in range(pbNumber): pblockBtn = QPushButton('物理块') pblockBtn.setCheckable(True) # pblockBtn.setFixedSize(90, 43) pblockBtn.setObjectName("parameBtn") pblockBtn.setIcon(qtawesome.icon('fa.th-large', color='#1fbb6f')) # pblockBtn.setCheckable(True) pblockBtn.clicked.connect(lambda _, pbbtn = pblockBtn: self.switchParameterWidget(pbbtn)) self.addWidget(pblockBtn, 3) self.buttonlist.append(pblockBtn) physicalBlockView = ParmView(PhysicalBlock, i, BlockType.PB) self.blockViewlist.append(physicalBlockView) if i == 0: pblockBtn.setChecked(True) for i in range(fbNumber): fblockBtn = QPushButton('功能块' + str(i + 1)) # fblockBtn.setFixedSize(90, 43) fblockBtn.setCheckable(True) fblockBtn.setObjectName("parameBtn") fblockBtn.setIcon(qtawesome.icon('fa.th-large', color='#1fbb6f')) fblockBtn.clicked.connect(lambda _, fbbtn = fblockBtn: self.switchParameterWidget(fbbtn)) self.addWidget(fblockBtn, 3) self.buttonlist.append(fblockBtn) aiFunctionBlockView = ParmView(AIFunctionBlock, i, BlockType.FB) self.blockViewlist.append(aiFunctionBlockView) for i, tbType in zip(range(tbNumber), self.tbtypeList): tbwidget = QWidget() tbwidget.setObjectName('tbwidget') tblayout = QHBoxLayout() tbwidget.setLayout(tblayout) tbcombox = TbCombox() # print(tbType) match tbType: case TBType.pressureTB: tbcombox.setCurrentIndex(0) tblockBtn = QPushButton(tbcombox.currentText() + str(i + 1)) case TBType.tempTB: tbcombox.setCurrentIndex(1) tblockBtn = QPushButton(tbcombox.currentText() + str(i + 1)) case TBType.levelTB: # print(2222) tbcombox.setCurrentIndex(2) tblockBtn = QPushButton(tbcombox.currentText() + str(i + 1)) case TBType.flowTB: tbcombox.setCurrentIndex(3) tblockBtn = QPushButton(tbcombox.currentText() + str(i + 1)) case None: tbcombox.setCurrentIndex(4) tblockBtn = QPushButton(tbcombox.currentText() + str(i + 1)) print(1) # tbcombox.setCurrentIndex(0) # tblockBtn = QPushButton('压力转换块' + str(i + 1)) tblockBtn.setObjectName("tbparameBtn") # tblockBtn.setFixedSize(130, 43) tblockBtn.setCheckable(True) tblockBtn.setIcon(qtawesome.icon('fa.th-large', color='#1fbb6f')) # tblockBtn.clicked.connect(lambda _, tbbtn = tblockBtn: self.switchParameterWidget(tbbtn)) tblockBtn.clicked.connect(lambda _, combox = tbcombox, tbbtn = tblockBtn : self.switchTbtype(combox.currentIndex(), combox, tbbtn)) tbcombox.currentIndexChanged.connect(lambda index, combox = tbcombox, tbbtn = tblockBtn : self.switchTbtype(index, combox, tbbtn)) tblayout.addWidget(tblockBtn, 6) tblayout.addWidget(tbcombox, 1) tblayout.setSpacing(0) self.addWidget(tbwidget, 5) self.buttonlist.append(tblockBtn) for tb, enum in zip(self.tbList, self.enumList): tbBlockView = ParmView(globals()[tb], i, enum) self.blockViewlist.append(tbBlockView) self.parameterButtonGroup = QButtonGroup() self.parameterButtonGroup.setExclusive(True) for button in self.buttonlist: self.parameterButtonGroup.addButton(button) self.parameStackWidget = QStackedWidget() for view in self.blockViewlist: self.parameStackWidget.addWidget(view) def switchParameterWidget(self, buttonType): for index , button in enumerate(self.buttonlist): if button == buttonType: self.parameStackWidget.setCurrentIndex(index) def switchTbtype(self, index, combox, button): tbType = combox.itemText(index) buttonNumber = button.text()[-1] button.setText(tbType + str(buttonNumber)) if button.isChecked(): stackIndex = (int(self.blocklist[0]) + int(self.blocklist[2]) + index) + (int(buttonNumber) - 1) * 5 print(stackIndex) self.parameStackWidget.setCurrentIndex(stackIndex) def deleteLater(self): while self.count(): item = self.takeAt(0) widget = item.widget() if widget: widget.deleteLater() layout = item.layout() if layout: layout.deleteLater() if self.parameStackWidget: while self.parameStackWidget.count(): widget = self.parameStackWidget.widget(0) self.parameStackWidget.removeWidget(widget) widget.deleteLater() self.parameStackWidget.deleteLater() super().deleteLater() class BlockParameterManageWidget(QWidget): def __init__(self): super().__init__() self.initUI() self._isPa = True self.initUIstat = True def initUI(self): self.mainlayout = QVBoxLayout() self.proTypeLabel = QLabel('PA协议') self.proTypeLabel.setAlignment(Qt.AlignVCenter | Qt.AlignRight) self.proTypeLabel.setObjectName('proTypeLabel') self.proTypeRadioBtn = QRadioButton() self.proTypeRadioBtn.setObjectName('proTypeRadioBtn') self.proTypeRadioBtn.toggled.connect(self.changeProType) self.settingLayout = QHBoxLayout() self.deviceAddressLabel = QLabel('从站地址') self.deviceAddressLabel.setObjectName('deviceAddressLabel') self.deviceAddressEdit = QLineEdit() self.deviceAddressEdit.returnPressed.connect(self.loadBlackData) self.deviceAddressEdit.setObjectName("deviceAddressEdit") self.confirmBtn = QPushButton('连接设备') self.confirmBtn.setIcon(qtawesome.icon('mdi.connection', color='#1fbb6f')) self.confirmBtn.clicked.connect(self.loadBlackData) self.confirmBtn.setObjectName("parameBtn") self.refershDataBtn = QPushButton('加载数据') self.refershDataBtn.setIcon(qtawesome.icon('mdi6.reload', color='#1fbb6f')) self.refershDataBtn.clicked.connect(self.refreshData) self.refershDataBtn.setObjectName("parameBtn") # self.deviceAddressSearchBtn = QPushButton('搜索站地址') # self.deviceAddressSearchBtn.setIcon(qtawesome.icon('fa.search', color='#1fbb6f')) # self.deviceAddressSearchBtn.clicked.connect(self.searchAddress) # self.deviceAddressSearchBtn.setObjectName("parameBtn") self.editAddressBtn = QPushButton('修改站地址') self.editAddressBtn.setIcon(qtawesome.icon('fa.edit', color='#1fbb6f')) self.editAddressBtn.clicked.connect(self.editAddress) self.editAddressBtn.setObjectName("parameBtn") self.settingLayout.addWidget(self.proTypeLabel, 1) self.settingLayout.addWidget(self.proTypeRadioBtn, 1) self.settingLayout.addWidget(self.deviceAddressLabel, 1) self.settingLayout.addWidget(self.deviceAddressEdit, 1) self.settingLayout.addWidget(self.confirmBtn, 1) # self.settingLayout.addWidget(self.deviceAddressSearchBtn, 1) self.settingLayout.addWidget(self.editAddressBtn, 1) self.settingLayout.addWidget(self.refershDataBtn, 1) # self.settingLayout.addLayout(self.blockLayout) # self.settingLayout.setSpacing(5) self.splitter = QSplitter() self.settingLayout.addWidget(self.splitter, 18) self.mainlayout.addLayout(self.settingLayout,1) self.widget = ShowImage('Static/pict.png') self.mainlayout.addWidget(self.widget, 20) self.setLayout(self.mainlayout) def loadBlackData(self): address = self.deviceAddressEdit.text() # print(address) if address: pattern = re.compile(r'^(?:[1-9]|[1-9][0-9]|1[0-1][0-9]|12[0-7])$') match = pattern.match(address) else: reply = QMessageBox.question(self.parent(), '警告', "请输入从站地址", QMessageBox.Yes) return if not match: QMessageBox.warning(self, '提示', '请输入2 - 127。') return if self.initUIstat: try: self.blockManage = BlockManage(self._isPa, int(address)) except Exception as e: reply = QMessageBox.question(self.parent(), '警告', f"发生错误: {e}", QMessageBox.Yes) return self.splitter.deleteLater() self.widget.deleteLater() self.splitter = QSplitter() Globals.setValue('blockManage', self.blockManage) blocklist = self.blockManage.getBlockNums() self.blockLayout = DynamicAddBlock(blocklist, self.blockManage.TBTypeList) self.settingLayout.addLayout(self.blockLayout, 7) self.settingLayout.addWidget(self.splitter, 11) self.mainlayout.addWidget(self.blockLayout.parameStackWidget, 20) self.initUIstat = False self.recordAddress = address #记录链接成功的站地址 else: reply = QMessageBox.question(self, '确定', '确定更换站地址吗?', QMessageBox.Yes | QMessageBox.No, QMessageBox.No) if reply == QMessageBox.Yes: try: self.blockManage = BlockManage(self._isPa, int(address)) except Exception as e: reply = QMessageBox.question(self.parent(), '警告', f"发生错误: {e}", QMessageBox.Yes) self.deviceAddressEdit.setText(self.recordAddress) return self.blockLayout.deleteLater() self.splitter.deleteLater() self.splitter = QSplitter() blocklist = self.blockManage.getBlockNums() TbtypeList = self.blockManage.TBTypeList self.blockLayout = DynamicAddBlock(blocklist, TbtypeList) self.settingLayout.addLayout(self.blockLayout, 7) self.settingLayout.addWidget(self.splitter, 11) self.mainlayout.addWidget(self.blockLayout.parameStackWidget, 20) self.recordAddress = address #记录链接成功的站地址 else: return def refreshData(self): if self.initUIstat: reply = QMessageBox.question(self.parent(), '警告', "请先连接设备", QMessageBox.Yes) return self.loadingDataWidget = LoadingDataWidget() self.loadingDataWidget.show() # self.loadingDataWidget.loadData() blockView = self.blockLayout.parameStackWidget.currentWidget() model = blockView.model # model.updateColumn(5, '查询中sdadadsda\r\nsdasdsasasad\r\nasdsadsad...') # blockView.resizeHeader() blockType = blockView.blockType blcokIndex = blockView.blcokIndex self.blockManage.getBlockValues(blockType = blockType, blockIndex = blcokIndex, callback = self.loadingDataWidget.loadData, callback2 = model.updateValue) # print(valueList) # model.updateValue(valueList) # print(blockType, blcokIndex) def editAddress(self): self.editAddressWidget = EditAddressWidget() # def searchAddress(self): # self.searchAddressWidget = SearchAddressWidget(self.deviceAddressEdit) # self.searchAddressWidget.show() def changeProType(self): if self.proTypeRadioBtn.isChecked(): self.proTypeLabel.setText('DP协议') self._isPa = False else: self.proTypeLabel.setText('PA协议') self._isPa = True self.clearLayout() def clearLayout(self): if self.initUIstat: return else: self.blockLayout.deleteLater() self.splitter.deleteLater() self.splitter = QSplitter() self.widget = ShowImage('Static/pict.png') self.mainlayout.addWidget(self.widget, 20) self.settingLayout.addWidget(self.splitter,18) self.initUIstat = True