日本免费高清视频-国产福利视频导航-黄色在线播放国产-天天操天天操天天操天天操|www.shdianci.com

學無先后,達者為師

網站首頁 編程語言 正文

Python?PyQt拖動控件對齊到網格的方法步驟_python

作者:@蘇丶 ? 更新時間: 2023-02-06 編程語言

實現如下需求:

在PyQt界面上有一個控件,實現其可任意拖動,且鼠標釋放時自動對齊到網格。

1.控件任意拖動并對齊到網格

如下按鈕(尺寸100×100),可任意拖動,釋放時對齊到網格(網格尺寸100×100)

首先給出代碼

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

欄目分類
最近更新