0721更新

main
parent dfd39c3d2d
commit 8011d136cd

@ -432,6 +432,20 @@ QLabel#deviceAddressLabel{
QLabel#oldAddressLabel{
font-size: 23px;
font: bold;
border: none;
font-family: ".SFNSDisplay-Medium";
}
QProgressBar {

Binary file not shown.

@ -1,7 +1,8 @@
import re
import qtawesome
from PyQt5.QtCore import Qt
from PyQt5.QtWidgets import QStyledItemDelegate, QStyle, QComboBox, QMessageBox, QPushButton,QStackedWidget, QLineEdit, QVBoxLayout, QHBoxLayout, QWidget, QLabel, QSplitter, QButtonGroup
from PyQt5.QtWidgets import QStyledItemDelegate, QStyle, QComboBox, QMessageBox, QPushButton,QStackedWidget, QLineEdit \
, QVBoxLayout, QHBoxLayout, QWidget, QLabel, QSplitter, QButtonGroup, QDialog
from utils.DBModels.DeviceParModels import *
from UI.BlockParameterView import ParmView
from UI.SearchAddressWidget import SearchAddressWidget
@ -9,11 +10,14 @@ 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 HideTextDelegate(QStyledItemDelegate):
def paint(self, painter, option, index):
# 仅在下拉列表中绘制文本避免在ComboBox显示区域绘制
@ -94,7 +98,7 @@ class DynamicAddBlock(QHBoxLayout):
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.addWidget(fblockBtn, 3)
self.buttonlist.append(fblockBtn)
aiFunctionBlockView = ParmView(AIFunctionBlock, i, BlockType.FB)
self.blockViewlist.append(aiFunctionBlockView)
@ -200,11 +204,17 @@ class BlockParameterManageWidget(QWidget):
self.deviceAddressSearchBtn.clicked.connect(self.searchAddress)
self.deviceAddressSearchBtn.setObjectName("parameBtn")
self.editAddressBtn = QPushButton('修改站地址')
self.editAddressBtn.setIcon(qtawesome.icon('fa.search', color='#1fbb6f'))
self.editAddressBtn.clicked.connect(self.editAddress)
self.editAddressBtn.setObjectName("parameBtn")
self.settingLayout.addWidget(self.deviceAddressLabel, 1)
self.settingLayout.addWidget(self.deviceAddressEdit, 1)
self.settingLayout.addWidget(self.confirmBtn, 1)
self.settingLayout.addWidget(self.refershDataBtn, 1)
self.settingLayout.addWidget(self.deviceAddressSearchBtn, 1)
self.settingLayout.addWidget(self.editAddressBtn, 1)
# self.settingLayout.addLayout(self.blockLayout)
self.splitter = QSplitter()
@ -292,7 +302,29 @@ class BlockParameterManageWidget(QWidget):
# print(blockType, blcokIndex)
def editAddress(self):
if self.initUIstat:
reply = QMessageBox.question(self.parent(),
'警告',
"请先连接设备",
QMessageBox.Yes)
return
oldAddress = self.blockManage.address
self.editAddressWidget = EditAddressWidget(oldAddress)
if self.editAddressWidget.exec_() == QDialog.Accepted:
newAddress = self.editAddressWidget.editAddressEdit.text()
self.blockManage.DPV1Master.editDevAddress(oldAddress, newAddress)
# if self.initUIstat:
# reply = QMessageBox.question(self.parent(),
# '警告',
# "请先连接设备",
# QMessageBox.Yes)
# return

@ -6,7 +6,8 @@ import re
import qtawesome
from PyQt5 import QtGui,QtCore,QtWidgets
from PyQt5.QtCore import QAbstractTableModel, QModelIndex, Qt, QVariant, QSize
from PyQt5.QtWidgets import QItemDelegate, QHBoxLayout, QWidget, QPushButton, QMessageBox, QLineEdit, QComboBox, QStyledItemDelegate, QVBoxLayout
from PyQt5.QtWidgets import QItemDelegate, QHBoxLayout, QWidget, QPushButton, QMessageBox, QLineEdit, \
QComboBox, QStyledItemDelegate, QVBoxLayout, QSplitter
from UI.LoadingDataWidget import LoadingDataWidget
from UI.ObjectTypeEditlayout import ObjectTypeEditlayout
@ -224,22 +225,22 @@ class VarButtonDelegate(QItemDelegate):
else:
parmIndex = model.datas[sender.index[0]][0]
values = objectTypeEditlayout.getEditlineValue()
if not values:
reply = QMessageBox.question(self.parent(),
'警告',
"请输入强制值或数字",
QMessageBox.Yes)
return
# if not values:
# reply = QMessageBox.question(self.parent(),
# '警告',
# "请输入强制值或数字",
# QMessageBox.Yes)
# return
for value in values:
# print(value)
pattern = re.compile(r'[^0-9\.-]+')
if not value or re.findall(pattern, str(value)):
reply = QMessageBox.question(self.parent(),
'警告',
"请输入强制值或数字",
QMessageBox.Yes)
return
# for value in values:
# # print(value)
# pattern = re.compile(r'[^0-9\.-]+')
# if not value or re.findall(pattern, str(value)):
# reply = QMessageBox.question(self.parent(),
# '警告',
# "请输入强制值或数字",
# QMessageBox.Yes)
# return
res = blockManage.writeParmValue(blockType, blockIndex, parmIndex, values)
self.refreshData()

@ -0,0 +1,367 @@
import sys
import re
from PyQt5 import QtCore, QtGui, QtWidgets
from PyQt5.QtCore import QSize, Qt
from PyQt5.Qt import *
from PyQt5.QtGui import QPixmap, QIcon
from PyQt5.QtWidgets import QHBoxLayout, QAbstractItemView, QVBoxLayout, QSplitter, \
QApplication, QLabel, QGridLayout, QLineEdit, QComboBox, QTextEdit, QCheckBox,QVBoxLayout,QListView, QMainWindow, QStackedWidget, QMessageBox
from PyQt5.QtWidgets import QSizePolicy, QWidget
from ctypes import POINTER, cast
from ctypes.wintypes import MSG
from PyQt5.QtWinExtras import QtWin
from win32 import win32api, win32gui
from win32.lib import win32con
from windoweffect.window_effect import WindowEffect
from windoweffect.c_structures import MINMAXINFO, NCCALCSIZE_PARAMS
from utils.DBModels.DeviceModels import DeviceDB
class EditAddressWidget(QDialog):
BORDER_WIDTH = 5 #设圆角
def __init__(self, address):
super().__init__()
self.address = address
self.initUI()
def initUI(self):
self.resize(306, 350)
self.setObjectName('deviceDialog')
self.editAddressEdit = QLineEdit()
self.editAddressEdit.setPlaceholderText("请输入站地址")
self.editAddressEdit.setSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Preferred)
self.editAddressEdit.setObjectName('deviceMesEdit')
self.oldAddressLabel = QLabel(' 当前站地址: ' + str(self.address))
self.oldAddressLabel.setSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Preferred)
self.oldAddressLabel.setObjectName('oldAddressLabel')
# self.pvLowerEdit = QLineEdit()
# self.pvLowerEdit.setPlaceholderText("量程下限")
# self.pvLowerEdit.setSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Preferred)
# self.pvLowerEdit.setObjectName('deviceMesEdit')
# self.pvUnitEdit = QLineEdit()
# self.pvUnitEdit.setPlaceholderText("单位")
# self.pvUnitEdit.setSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Preferred)
# self.pvUnitEdit.setObjectName('deviceMesEdit')
self.confirmButton = QPushButton('确定')
self.confirmButton.setObjectName('confirmButton')
self.confirmButton.clicked.connect(self.checkInput)
enterShortcut = QtWidgets.QShortcut(QtGui.QKeySequence(QtCore.Qt.Key_Return), self)
enterShortcut.activated.connect(self.confirmButton.click)
self.exitButton = QPushButton('取消')
self.exitButton.clicked.connect(self.close)
self.exitButton.setObjectName('exitButton')
self.horizontalLayout = QHBoxLayout()
self.horizontalLayout.addWidget(self.confirmButton)
self.horizontalLayout.addWidget(self.exitButton)
self.horizontalLayout.setSpacing(10)
self.horizontalLayout.setContentsMargins(0, 0, 0, 0)
self.verticalLayout = QVBoxLayout(self)
self.conVerLayout = QVBoxLayout()
self.conVerLayout.addWidget(QSplitter(), 1)
self.conVerLayout.addWidget(self.oldAddressLabel, 2)
self.conVerLayout.addWidget(self.editAddressEdit, 2)
# self.conVerLayout.addWidget(self.pvLowerEdit, 1)
# self.conVerLayout.addWidget(self.pvUnitEdit, 1)
# self.conVerLayout.addWidget(QSplitter(), 1)
self.conVerLayout.addLayout(self.horizontalLayout, 2)
self.conVerLayout.setSpacing(32)
self.conVerLayout.setContentsMargins(34, 26, 34, 50)
# self.verticalLayout.addWidget(self.picLabel)
self.verticalLayout.addLayout(self.conVerLayout)
self.verticalLayout.setSpacing(10)
self.verticalLayout.setContentsMargins(0, 0, 0, 0)
self.setLayout(self.verticalLayout)
# 设置模态窗口
self.setWindowFlags(self.windowFlags() | Qt.Window)
self.setWindowModality(Qt.ApplicationModal)
self.setWindowFlags(Qt.FramelessWindowHint|Qt.WindowSystemMenuHint)
self.SHADOW_WIDTH = 0 #边框距离
self.isLeftPressDown = False #鼠标左键是否按下
self.dragPosition = 0 #拖动时坐标
self.padding = 4
self.Numbers = self.enum(UP=0, DOWN=1, LEFT=2, RIGHT=3, LEFTTOP=4, LEFTBOTTOM=5, RIGHTBOTTOM=6, RIGHTTOP=7, NONE=8) #枚举参数
self.setMinimumHeight(350) #窗体最小高度
self.setMinimumWidth(306) #窗体最小宽度
self.dir = self.Numbers.NONE #初始鼠标状态
#开启鼠标追踪
self.setMouseTracking(True)
#初始化接口
self.windowEffect = WindowEffect()
# 添加DWM阴影效果
self.windowEffect.addWindowAnimation(self.winId())
self.windowEffect.addShadowEffect(self.winId())
# 解决报错
self.windowHandle().screenChanged.connect(self.__onScreenChanged)
self.setWindowOpacity(0.995) # 设置窗口透明度
self.setWindowFlag(Qt.FramelessWindowHint)
def checkInput(self):
newaddress = self.editAddressEdit.text()
if not newaddress:
reply = QMessageBox.question(self.parent(),
'警告',
"请先连接设备",
QMessageBox.Yes)
return
else:
self.accept() # 所有输入都是数字且不为空时接受对话框
def enum(self,**enums):
return type('Enum', (), enums)
def region(self,cursorGlobalPoint):
#获取窗体在屏幕上的位置区域tl为topleft点rb为rightbottom点
rect = self.rect()
tl = self.mapToGlobal(rect.topLeft())
rb = self.mapToGlobal(rect.bottomRight())
x = cursorGlobalPoint.x()
y = cursorGlobalPoint.y()
if(tl.x() + self.padding >= x and tl.x() <= x and tl.y() + self.padding >= y and tl.y() <= y):
#左上角
self.dir = self.Numbers.LEFTTOP
self.setCursor(QCursor(Qt.SizeFDiagCursor)) #设置鼠标形状
elif(x >= rb.x() - self.padding and x <= rb.x() and y >= rb.y() - self.padding and y <= rb.y()):
#右下角
self.dir = self.Numbers.RIGHTBOTTOM
self.setCursor(QCursor(Qt.SizeFDiagCursor))
elif(x <= tl.x() + self.padding and x >= tl.x() and y >= rb.y() - self.padding and y <= rb.y()):
#左下角
self.dir = self.Numbers.LEFTBOTTOM
self.setCursor(QCursor(Qt.SizeBDiagCursor))
elif(x <= rb.x() and x >= rb.x() - self.padding and y >= tl.y() and y <= tl.y() + self.padding):
#右上角
self.dir = self.Numbers.RIGHTTOP
self.setCursor(QCursor(Qt.SizeBDiagCursor))
elif(x <= tl.x() + self.padding and x >= tl.x()):
#左边
self.dir = self.Numbers.LEFT
self.setCursor(QCursor(Qt.SizeHorCursor))
elif( x <= rb.x() and x >= rb.x() - self.padding):
#右边
self.dir = self.Numbers.RIGHT
self.setCursor(QCursor(Qt.SizeHorCursor))
elif(y >= tl.y() and y <= tl.y() + self.padding):
#上边
self.dir = self.Numbers.UP
self.setCursor(QCursor(Qt.SizeVerCursor))
elif(y <= rb.y() and y >= rb.y() - self.padding):
#下边
self.dir = self.Numbers.DOWN
self.setCursor(QCursor(Qt.SizeVerCursor))
else:
#默认
self.dir = self.Numbers.NONE
self.setCursor(QCursor(Qt.ArrowCursor))
def mouseReleaseEvent(self,event):
if(event.button() == Qt.LeftButton):
self.isLeftPressDown = False
if(self.dir != self.Numbers.NONE):
self.releaseMouse()
self.setCursor(QCursor(Qt.ArrowCursor))
def mousePressEvent(self,event):
if(event.button()==Qt.LeftButton):
self.isLeftPressDown=True
if(self.dir != self.Numbers.NONE):
self.mouseGrabber()
else:
self.dragPosition = event.globalPos() - self.frameGeometry().topLeft()
def mouseMoveEvent(self,event):
gloPoint = event.globalPos()
rect = self.rect()
tl = self.mapToGlobal(rect.topLeft())
rb = self.mapToGlobal(rect.bottomRight())
if(not self.isLeftPressDown):
self.region(gloPoint)
else:
if(self.dir != self.Numbers.NONE):
rmove=QRect(tl, rb)
if(self.dir==self.Numbers.LEFT):
if(rb.x() - gloPoint.x() <= self.minimumWidth()):
rmove.setX(tl.x())
else:
rmove.setX(gloPoint.x())
elif(self.dir==self.Numbers.RIGHT):
rmove.setWidth(gloPoint.x() - tl.x())
elif(self.dir==self.Numbers.UP):
if(rb.y() - gloPoint.y() <= self.minimumHeight()):
rmove.setY(tl.y())
else:
rmove.setY(gloPoint.y())
elif(self.dir==self.Numbers.DOWN):
rmove.setHeight(gloPoint.y() - tl.y())
elif(self.dir==self.Numbers.LEFTTOP):
if(rb.x() - gloPoint.x() <= self.minimumWidth()):
rmove.setX(tl.x())
else:
rmove.setX(gloPoint.x())
if(rb.y() - gloPoint.y() <= self.minimumHeight()):
rmove.setY(tl.y())
else:
rmove.setY(gloPoint.y())
elif(self.dir==self.Numbers.RIGHTTOP):
rmove.setWidth(gloPoint.x() - tl.x())
rmove.setY(gloPoint.y())
elif(self.dir==self.Numbers.LEFTBOTTOM):
rmove.setX(gloPoint.x())
rmove.setHeight(gloPoint.y() - tl.y())
elif(self.dir==self.Numbers.RIGHTBOTTOM):
rmove.setWidth(gloPoint.x() - tl.x())
rmove.setHeight(gloPoint.y() - tl.y())
else:
pass
self.setGeometry(rmove)
else:
self.move(event.globalPos() - self.dragPosition)
event.accept()
def nativeEvent(self, eventType, message):
""" 接受windows发送的信息 """
msg = MSG.from_address(message.__int__())
if msg.message == win32con.WM_NCHITTEST:
# 解决 issue #2 and issue #7
r = self.devicePixelRatioF()
xPos = (win32api.LOWORD(msg.lParam) -
self.frameGeometry().x()*r) % 65536
yPos = win32api.HIWORD(msg.lParam) - self.frameGeometry().y()*r
w, h = self.width()*r, self.height()*r
lx = xPos < self.BORDER_WIDTH
rx = xPos + 9 > w - self.BORDER_WIDTH
ty = yPos < self.BORDER_WIDTH
by = yPos > h - self.BORDER_WIDTH
if lx and ty:
return True, win32con.HTTOPLEFT
elif rx and by:
return True, win32con.HTBOTTOMRIGHT
elif rx and ty:
return True, win32con.HTTOPRIGHT
elif lx and by:
return True, win32con.HTBOTTOMLEFT
elif ty:
return True, win32con.HTTOP
elif by:
return True, win32con.HTBOTTOM
elif lx:
return True, win32con.HTLEFT
elif rx:
return True, win32con.HTRIGHT
elif msg.message == win32con.WM_NCCALCSIZE:
if self.__isWindowMaximized(msg.hWnd):
self.__monitorNCCALCSIZE(msg)
return True, 0
elif msg.message == win32con.WM_GETMINMAXINFO:
if self.__isWindowMaximized(msg.hWnd):
window_rect = win32gui.GetWindowRect(msg.hWnd)
if not window_rect:
return False, 0
# get the monitor handle
monitor = win32api.MonitorFromRect(window_rect)
if not monitor:
return False, 0
# get the monitor info
__monitorInfo = win32api.GetMonitorInfo(monitor)
monitor_rect = __monitorInfo['Monitor']
work_area = __monitorInfo['Work']
# convert lParam to MINMAXINFO pointer
info = cast(msg.lParam, POINTER(MINMAXINFO)).contents
# adjust the size of window
info.ptMaxSize.x = work_area[2] - work_area[0]
info.ptMaxSize.y = work_area[3] - work_area[1]
info.ptMaxTrackSize.x = info.ptMaxSize.x
info.ptMaxTrackSize.y = info.ptMaxSize.y
# modify the upper left coordinate
info.ptMaxPosition.x = abs(window_rect[0] - monitor_rect[0])
info.ptMaxPosition.y = abs(window_rect[1] - monitor_rect[1])
return True, 1
return QWidget.nativeEvent(self, eventType, message)
def __isWindowMaximized(self, hWnd) -> bool:
""" Determine whether the window is maximized """
# GetWindowPlacement() returns the display state of the window and the restored,
# maximized and minimized window position. The return value is tuple
windowPlacement = win32gui.GetWindowPlacement(hWnd)
if not windowPlacement:
return False
return windowPlacement[1] == win32con.SW_MAXIMIZE
def __monitorNCCALCSIZE(self, msg: MSG):
""" 调整窗口大小 """
monitor = win32api.MonitorFromWindow(msg.hWnd)
# If the display information is not saved, return directly
if monitor is None and not self.__monitorInfo:
return
elif monitor is not None:
self.__monitorInfo = win32api.GetMonitorInfo(monitor)
# adjust the size of window
params = cast(msg.lParam, POINTER(NCCALCSIZE_PARAMS)).contents
params.rgrc[0].left = self.__monitorInfo['Work'][0]
params.rgrc[0].top = self.__monitorInfo['Work'][1]
params.rgrc[0].right = self.__monitorInfo['Work'][2]
params.rgrc[0].bottom = self.__monitorInfo['Work'][3]
def __onScreenChanged(self):
hWnd = int(self.windowHandle().winId())
win32gui.SetWindowPos(hWnd, None, 0, 0, 0, 0, win32con.SWP_NOMOVE |
win32con.SWP_NOSIZE | win32con.SWP_FRAMECHANGED)
if __name__ == '__main__':
app = QApplication(sys.argv)
app.setStyle(QtWidgets.QStyleFactory.create('Fusion'))
# print(QtWidgets.QStyleFactory.keys())
ex = LoginWidget()
ex.show()
sys.exit(app.exec_())

@ -107,7 +107,13 @@ class Parm():
return str(round(struct.unpack('>f', value)[0], 4))
def unpackStr(self, value):
return struct.unpack('{}s'.format(str(len(value))), value)[0]
# return struct.unpack('{}s'.format(str(len(value))), value)[0]
# print(value,2222)
# print(struct.unpack('{}s'.format(str(len(value))), value)[0])
try:
return value.decode('ASCII')
except Exception as e:
print(e)
def unpack101(self, value):
valueByte, statusByte = value[:4], value[4].to_bytes(1, byteorder='little')
@ -117,6 +123,7 @@ class Parm():
return displayStr
def unpackDS32(self, value):
print(value)
reserved = self.unpackU8(value[0:1])
blockObject = self.unpackU8(value[1:2])
parentClass = self.unpackU8(value[2:3])
@ -222,3 +229,6 @@ class Parm():
def unitConver(self, unitValue):
unit, desc = '1', '1'
return unit + desc
def packStr(self, value):
return struct.pack('>{}s'.format(len(value)), value.encode('ASCII'))

@ -102,7 +102,7 @@ class DPV1Master():
writeByteStream = b'\x02' + hexAddress + slotByte + indexByte + lengthByte + valueByte
writeByteStream = writeByteStream if len(writeByteStream) % 2 == 0 else writeByteStream + b'\x00'
self.writeMultipleRegister(1, 750, self.resetData)
print(len(writeByteStream))
# print(len(writeByteStream))
writeDate = struct.unpack('>{}h'.format(len(writeByteStream) // 2), writeByteStream)
self.writeMultipleRegister(1, 750, writeDate)
time.sleep(0.3)
@ -129,6 +129,23 @@ class DPV1Master():
else:
return False
def editDevAddress(self, oldAddress, newAddress):
oldAddressHex = int(oldAddress).to_bytes(1, byteorder='little')
newAddressHex = int(newAddress).to_bytes(1, byteorder='little')
editAddressStream = b'\x03' + oldAddressHex + newAddressHex + b'\x00'
editAddressDate = struct.unpack('>hh', editAddressStream)
self.writeMultipleRegister(1, 750, self.resetData)
self.writeMultipleRegister(1, 750, editAddressDate)
time.sleep(0.3)
value = self.readHoldingRegisters(1, 750, 2)
if value[0] == 57344:
result = '修改错误'
else:
result = '修改成功'
self.writeMultipleRegister(1, 750, self.resetData)
time.sleep(0.1)
return result
# def readInputRegisters(self, slaveId, startAddress, varNums, order = 'ABCD'):
# try:

Loading…
Cancel
Save