You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
PROFIBUS/UI/EditAddressWidget.py

415 lines
17 KiB
Python

1 year ago
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
1 year ago
from model.ConfigModel.GSDManage import GsdParser
1 year ago
1 year ago
from protocol.ModBus.DPV1Master import DPV1Master
1 year ago
class EditAddressWidget(QDialog):
BORDER_WIDTH = 5 #设圆角
1 year ago
def __init__(self):
1 year ago
super().__init__()
self.initUI()
def initUI(self):
self.resize(306, 350)
self.setObjectName('deviceDialog')
1 year ago
self.newAddressEdit = QLineEdit()
self.newAddressEdit.setPlaceholderText("请输入目标站地址")
self.newAddressEdit.setSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Preferred)
self.newAddressEdit.setObjectName('deviceMesEdit')
1 year ago
1 year ago
self.oldAddressEdit = QLineEdit()
self.oldAddressEdit.setPlaceholderText("请输入原站地址")
self.oldAddressEdit.setSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Preferred)
self.oldAddressEdit.setObjectName('deviceMesEdit')
# self.oldAddressLabel = QLabel(' 请输入原站地址: ' + str(self.address))
# self.oldAddressLabel.setSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Preferred)
# self.oldAddressLabel.setObjectName('oldAddressLabel')
1 year ago
# 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)
1 year ago
self.deviceTypeCombox = QComboBox()
self.deviceTypeCombox.setObjectName('deviceTypeCombox')
# self.deviceTypeCombox.addItems(['1', '2'])
self.addCheckItem()
1 year ago
# self.deviceTypeCombox.currentIndexChanged.connect(lambda index: self.changeDeviceType(index = index))
1 year ago
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)
1 year ago
self.conVerLayout.addWidget(self.oldAddressEdit, 2)
self.conVerLayout.addWidget(self.newAddressEdit, 2)
self.conVerLayout.addWidget(self.deviceTypeCombox, 2)
1 year ago
# 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)
1 year ago
1 year ago
# 设置模态窗口
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)
1 year ago
self.DPV1Master = DPV1Master('192.168.3.10', 502)
1 year ago
1 year ago
self.exec_()
# def changeDeviceType(self, index):
# print(index)
1 year ago
1 year ago
def addCheckItem(self):
1 year ago
self.GSDData = GsdParser.parseGsdFiles()
1 year ago
# deviceTypeCombox
for GSDDict in self.GSDData:
self.deviceTypeCombox.addItem(GSDDict['modelName'])
1 year ago
def checkInput(self):
1 year ago
oldAddress = self.oldAddressEdit.text()
newAddress = self.newAddressEdit.text()
if newAddress and oldAddress:
pattern = re.compile(r'^(?:[1-9]|[1-9][0-9]|1[0-1][0-9]|12[0-6])$')
oldmatch = pattern.match(oldAddress)
newmatch = pattern.match(newAddress)
if not oldmatch:
QMessageBox.warning(self, '提示', '请输入2 - 126。')
return
if not newmatch:
QMessageBox.warning(self, '提示', '请输入2 - 126。')
return
if oldAddress == newAddress:
1 year ago
reply = QMessageBox.question(self.parent(),
1 year ago
'警告',
"站地址重复",
QMessageBox.Yes)
1 year ago
return
else:
1 year ago
reply = QMessageBox.question(self.parent(),
'警告',
"请输入从站地址",
QMessageBox.Yes)
return
1 year ago
1 year ago
identNumber = self.GSDData[self.deviceTypeCombox.currentIndex()]['identNumber']
1 year ago
print(identNumber)
1 year ago
oldAddress = int(oldAddress)
newAddress = int(newAddress)
result = self.DPV1Master.editDevAddress(oldAddress, newAddress, identNumber)
reply = QMessageBox.question(self.parent(),
'提示',
result,
QMessageBox.Yes)
self.accept()
1 year ago
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_())