Python PyQt拖动控件对齐到网格的方法步骤

作者:@苏丶 时间:2022-05-04 19:25:00 

实现如下需求:

在PyQt界面上有一个控件,实现其可任意拖动,且鼠标释放时自动对齐到网格。

1.控件任意拖动并对齐到网格

如下按钮(尺寸100×100),可任意拖动,释放时对齐到网格(网格尺寸100×100)

Python PyQt拖动控件对齐到网格的方法步骤

Python PyQt拖动控件对齐到网格的方法步骤

首先给出代码

from PyQt5.QtWidgets import QPushButton, QMainWindow, QApplication

class Button(QPushButton):
   def __init__(self, parent=None):
       super().__init__(parent)
       self.resize(100, 100)

self.pos1 = 0  # 用于拖动时的鼠标位置初始值

def mousePressEvent(self, QMouseEvent):
       self.pos1 = QMouseEvent.screenPos()

def mouseReleaseEvent(self, QMouseEvent) -> None:
       fx, fy = self.frameGeometry().x(), self.frameGeometry().y()  # 相对父控件坐标
       tx_index, ty_index = fx // 100 if fx > 99 else 0, fy // 100 if fy > 99 else 0
       # 移动到网格上
       self.mymove(tx_index, ty_index)

def mouseMoveEvent(self, QMouseEvent):
       pos2 = QMouseEvent.screenPos()
       tx = int(self.frameGeometry().x() + pos2.x() - self.pos1.x())
       ty = int(self.frameGeometry().y() + pos2.y() - self.pos1.y())
       self.move(tx, ty)
       self.pos1 = pos2

def mymove(self, tx_index, ty_index):
       self.move(tx_index * 100, ty_index * 100)

class MainWindow(QMainWindow):
   def __init__(self):
       super().__init__()

self.setWindowTitle('按钮测试')
       self.resize(500, 500)

self.btn = Button(self)
       self.btn.setText('ABCD')

if __name__ == "__main__":
   import sys

app = QApplication(sys.argv)
   mw = MainWindow()
   mw.show()
   sys.exit(app.exec_())

这里自定义Button类继承QPushButton类,因为我们需要重写鼠标移动的方法来实现所需功能。

要实现任意拖动,按钮必须跟随鼠标,于是我们重写mousePressEvent方法和mouseMoveEvent方法。

  1. 当我们按下鼠标时,触发mousePress事件,记录此刻光标位置;

  2. 当光标拖动时触发mouseMove事件,获取当前光标位置,计算与之前位置的x和y的差值,然后加到按钮的相对坐标上,获得按钮需要移动到的位置坐标;

  3. 调用move方法移动按钮;

  4. 更新pos1即按钮位置;

  5. 只要光标移动,就会触发mouseMove事件,就会不断移动按钮与更新按钮位置,在视觉上按钮就是在跟着光标任意拖动。

要实现鼠标释放时对齐到网格,需要重写mouseReleaseEvent方法,用来响应鼠标释放动作。

  1. 当鼠标释放时,立即读取按钮的当前相对坐标;

  2. 将按钮的坐标除以100用来获取其在网格上的位置,如果坐标小于0应令其等于0,同时0-99的坐标除以100也等于0,于是只要小于99就等于0;

  3. 然后调用自定义的mymove方法,在这个方法中,将网格位置换算到相对坐标,再调用move方法使其移动到网格。

2.进阶:双击控件使其移动到其他网格

移动并对齐到网格的功能已经在上一部分实现了,这里需要实现鼠标双击动作,首先给出代码

from PyQt5.QtWidgets import QPushButton, QMainWindow, QApplication
from PyQt5.QtCore import Qt

class Button(QPushButton):
   def __init__(self, parent=None):
       super().__init__(parent)
       self.resize(100, 100)

self.pos1 = 0  # 用于拖动时的鼠标位置初始值
       self.x_index, self.y_index = 0, 0  # 记录按钮在网格上的位置

def mousePressEvent(self, QMouseEvent):
       if QMouseEvent.buttons() == Qt.LeftButton:
           print('左键按下')
           self.pos1 = QMouseEvent.screenPos()
       elif QMouseEvent.buttons() == Qt.RightButton:
           print('右键按下')
           self.pos1 = QMouseEvent.screenPos()

def mouseReleaseEvent(self, QMouseEvent) -> None:
       print('鼠标释放')
       fx, fy = self.frameGeometry().x(), self.frameGeometry().y()  # 相对父控件坐标
       tx_index, ty_index = fx // 100 if fx > 99 else 0, fy // 100 if fy > 99 else 0
       # 移动到网格上
       self.x_index, self.y_index = tx_index, ty_index
       self.mymove(tx_index, ty_index)

def mouseDoubleClickEvent(self, QMouseEvent):
       if QMouseEvent.buttons() == Qt.LeftButton:
           print('左键双击')
           self.x_index += 1
           self.y_index += 1
           self.mymove(self.x_index, self.y_index)
       elif QMouseEvent.buttons() == Qt.RightButton:
           print('右键双击')

def mouseMoveEvent(self, QMouseEvent):
       if QMouseEvent.buttons() == Qt.LeftButton:
           pos2 = QMouseEvent.screenPos()
           tx = int(self.frameGeometry().x() + pos2.x() - self.pos1.x())
           ty = int(self.frameGeometry().y() + pos2.y() - self.pos1.y())
           self.move(tx, ty)
           self.pos1 = pos2

def mymove(self, tx_index, ty_index):
       self.move(tx_index * 100, ty_index * 100)
       print(f'按钮移动到({tx_index}, {ty_index})')

class MainWindow(QMainWindow):
   def __init__(self):
       super().__init__()

self.setWindowTitle('按钮测试')
       self.resize(500, 500)

self.btn = Button(self)
       self.btn.setText('ABCD')

if __name__ == "__main__":
   import sys

app = QApplication(sys.argv)
   mw = MainWindow()
   mw.show()
   sys.exit(app.exec_())

在这里多了一些实例属性,如self.x_index, self.y_index用来记录按钮在网格上的位置。

要实现双击动作,必须重写mouseDoubleClickEvent方法,在mouseDoubleClickEvent方法中,我们首先将self.x_index, self.y_index进行修改,以更改按钮要移动到的位置,然后调用mymove方法进行移动。

此外,代码还进行了左键与右键的判断,当左键进行操作时,按钮可以更改位置,右键操作时不可更改。

来源:https://blog.csdn.net/weixin_42147967/article/details/128486736

标签:pyqt,拖拽,控件
0
投稿

猜你喜欢

  • asp好用的函数集分享

    2011-09-13 12:49:07
  • Access2000迁移到Oracle9i要点

    2010-07-27 13:10:00
  • Uchome1.2 1.5 代码学习 common.php

    2023-11-15 02:56:10
  • Python基于scrapy采集数据时使用代理服务器的方法

    2022-06-03 08:37:04
  • 如何恢复/修复SQL Server的MDF文件

    2008-11-24 15:30:00
  • XMLHTTPRequest的属性和方法简介

    2007-12-18 18:42:00
  • 解析:以mysql_开始的未定义引用错误

    2008-12-19 17:58:00
  • 解决python3 HTMLTestRunner测试报告中文乱码的问题

    2021-10-19 04:34:06
  • php用header函数实现301跳转代码实例

    2023-10-08 11:29:59
  • 天极网页版式设计的思考

    2008-01-18 12:44:00
  • 未能找到存储过程’master.dbo.xp_fileexist’解决方法

    2011-03-13 09:29:00
  • python新手练习实例之万年历

    2021-01-29 02:20:35
  • asp 使用正则表达式替换word中的标签,转为纯文本

    2011-02-28 10:49:00
  • 如何使用Python实现自动化水军评论

    2022-08-25 21:15:48
  • 数据库手边系列:SQL Server数据表信息

    2009-05-24 18:26:00
  • vuejs实现下拉框菜单选择

    2023-09-23 08:49:54
  • Pytest单元测试框架生成HTML测试报告及优化的步骤

    2021-07-10 16:49:13
  • asp 动态数组 提供Add、Insert、Remove、RemoveAt、Search等方法。

    2011-03-17 11:10:00
  • 如何防止页面中的敏感信息被提取

    2008-05-04 11:59:00
  • Python如何定义有默认参数的函数

    2023-08-05 14:38:30
  • asp之家 网络编程 m.aspxhome.com