|
|
|
@ -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_())
|