注:系列文章,前后关联,请结合完整代码参考本系列文章;现已开源在 GitHub PyOc
事件
- 鼠标按下事件
[virtual protected] void QWidget::mousePressEvent(QMouseEvent *event)
def mousePressEvent(self, event):
"""重写继承的鼠标按住事件"""
self._isPressed = True # 判断是否按下
self._press_button = event.button() # 按下的鼠标按键
self._area = self._compute_area(event.pos()) # 计算鼠标所在区域
self._move_count = 0 # 鼠标移动计数,用于降低灵敏度
self._posLast = event.globalPos() # 当前坐标
return QMainWindow.mousePressEvent(self, event) # 交由原事件函数处理
- 鼠标释放事件
[virtual protected] void QWidget::mouseReleaseEvent(QMouseEvent *event)
def mouseReleaseEvent(self, event):
"""重写继承的鼠标释放事件"""
self._isPressed = False # 重置按下状态
self._press_button = None # 清空按下的鼠标按键
self._area = None # 清空鼠标区域
self._move_count = 0 # 清空移动计数
self.setCursor(Qt.ArrowCursor) # 还原光标图标
return QMainWindow.mouseReleaseEvent(self, event)
- 鼠标移动事件
[virtual protected] void QWidget::mouseMoveEvent(QMouseEvent *event)
def mouseMoveEvent(self, event):
"""重写继承的鼠标移动事件,实现窗口移动及拖动改变窗口大小"""
area = self._compute_area(event.pos()) # 计算鼠标区域
# 调整窗口大小及移动
if self._isPressed and self._press_button == Qt.LeftButton:
if self._area == 22:
self._move(event) # 调用移动窗口的函数
elif not self.isMaximized():
self._resize(event) # 调用调整窗口大小的函数
# 更新鼠标全局坐标
self._posLast = event.globalPos()
return None
if not self._isPressed and not self.isMaximized():
# 调整鼠标图标,按下鼠标后锁定状态
self._change_cursor_icon(area)
return QMainWindow.mouseMoveEvent(self, event)
计算窗口区域
- 计算鼠标在窗口中的区域
def _compute_area(self, pos):
"""计算鼠标在窗口中的区域
Args:
pos: 鼠标相对于窗口的位置
"""
margin = self.MARGIN # 以此值为外边框宽度,划为九宫格区域
# 定位列坐标
if pos.x() < margin:
line = 1
elif pos.x() > self.width() - margin:
line = 3
else:
line = 2
# 定位行坐标并结合列坐标
if pos.y() < margin:
return 10 + line
elif pos.y() > self.height() - margin:
return 30 + line
else:
return 20 + line
- 辅助函数,返回鼠标在窗口中的纵横百分比
def _pos_percent(self, pos):
"""返回鼠标相对窗口的纵横百分比"""
if pos.x() <= 0:
x = 0
else:
x = round(pos.x() / self.width(), 3)
if pos.y() <= 0:
y = 0
else:
y = round(pos.y() / self.height(), 3)
return x, y
移动窗口
- 移动窗口,最大化时需还原窗口状态
def _move(self, event):
"""实现窗口移动"""
self._move_count += 1
# 判断移动次数,减少灵敏度
if self._move_count < self.MOVE_SENSITIVITY:
return None
# 最大化时需恢复普通大小,并按相对坐标移动到鼠标位置
# 普通状态的宽高在窗口最大化之前获取,需借助标题栏的最大化按钮槽函数
if self.isMaximized():
relative = self._pos_percent(event.pos())
self.titlebar.max_button_click()
gpos = event.globalPos()
width = self._last_geometry.width() # 普通大小的几何属性
height = self._last_geometry.height()
x = gpos.x() - round(width * relative[0])
y = gpos.y() - round(height * relative[1])
self.setGeometry(x, y, width, height)
else:
# 鼠标移动偏移量
offsetPos = event.globalPos() - self._posLast
# ~ print(self.pos(), '->', self.pos() + offsetPos)
self.move(self.pos() + offsetPos)
本文为 one-ccs 原创文章,引用必须注明出处!
https://blog.csdn.net/qq_43155814/article/details/104676865