Python?PyQt拖動控件對齊到網(wǎng)格的方法步驟
實現(xiàn)如下需求:
在PyQt界面上有一個控件,實現(xiàn)其可任意拖動,且鼠標(biāo)釋放時自動對齊到網(wǎng)格。
1.控件任意拖動并對齊到網(wǎng)格
如下按鈕(尺寸100×100),可任意拖動,釋放時對齊到網(wǎng)格(網(wǎng)格尺寸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 # 用于拖動時的鼠標(biāo)位置初始值 def mousePressEvent(self, QMouseEvent): self.pos1 = QMouseEvent.screenPos() def mouseReleaseEvent(self, QMouseEvent) -> None: fx, fy = self.frameGeometry().x(), self.frameGeometry().y() # 相對父控件坐標(biāo) tx_index, ty_index = fx // 100 if fx > 99 else 0, fy // 100 if fy > 99 else 0 # 移動到網(wǎng)格上 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類,因為我們需要重寫鼠標(biāo)移動的方法來實現(xiàn)所需功能。
要實現(xiàn)任意拖動,按鈕必須跟隨鼠標(biāo),于是我們重寫mousePressEvent方法和mouseMoveEvent方法。
- 當(dāng)我們按下鼠標(biāo)時,觸發(fā)mousePress事件,記錄此刻光標(biāo)位置;
- 當(dāng)光標(biāo)拖動時觸發(fā)mouseMove事件,獲取當(dāng)前光標(biāo)位置,計算與之前位置的x和y的差值,然后加到按鈕的相對坐標(biāo)上,獲得按鈕需要移動到的位置坐標(biāo);
- 調(diào)用move方法移動按鈕;
- 更新pos1即按鈕位置;
- 只要光標(biāo)移動,就會觸發(fā)mouseMove事件,就會不斷移動按鈕與更新按鈕位置,在視覺上按鈕就是在跟著光標(biāo)任意拖動。
要實現(xiàn)鼠標(biāo)釋放時對齊到網(wǎng)格,需要重寫mouseReleaseEvent方法,用來響應(yīng)鼠標(biāo)釋放動作。
- 當(dāng)鼠標(biāo)釋放時,立即讀取按鈕的當(dāng)前相對坐標(biāo);
- 將按鈕的坐標(biāo)除以100用來獲取其在網(wǎng)格上的位置,如果坐標(biāo)小于0應(yīng)令其等于0,同時0-99的坐標(biāo)除以100也等于0,于是只要小于99就等于0;
- 然后調(diào)用自定義的mymove方法,在這個方法中,將網(wǎng)格位置換算到相對坐標(biāo),再調(diào)用move方法使其移動到網(wǎng)格。
2.進(jìn)階:雙擊控件使其移動到其他網(wǎng)格
移動并對齊到網(wǎng)格的功能已經(jīng)在上一部分實現(xiàn)了,這里需要實現(xiàn)鼠標(biāo)雙擊動作,首先給出代碼
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 # 用于拖動時的鼠標(biāo)位置初始值 self.x_index, self.y_index = 0, 0 # 記錄按鈕在網(wǎng)格上的位置 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('鼠標(biāo)釋放') fx, fy = self.frameGeometry().x(), self.frameGeometry().y() # 相對父控件坐標(biāo) tx_index, ty_index = fx // 100 if fx > 99 else 0, fy // 100 if fy > 99 else 0 # 移動到網(wǎng)格上 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用來記錄按鈕在網(wǎng)格上的位置。
要實現(xiàn)雙擊動作,必須重寫mouseDoubleClickEvent方法,在mouseDoubleClickEvent方法中,我們首先將self.x_index, self.y_index進(jìn)行修改,以更改按鈕要移動到的位置,然后調(diào)用mymove方法進(jìn)行移動。
此外,代碼還進(jìn)行了左鍵與右鍵的判斷,當(dāng)左鍵進(jìn)行操作時,按鈕可以更改位置,右鍵操作時不可更改。
總結(jié)
到此這篇關(guān)于Python PyQt拖動控件對齊到網(wǎng)格的文章就介紹到這了,更多相關(guān)PyQt拖動控件對齊到網(wǎng)格內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
python獲取異常信息exc_info和print_exc的使用
python通過sys.exc_info獲取異常信息,通過traceback.print_exc打印堆棧信息,包括錯誤類型和錯誤位置等信息,本文就來介紹一下具體用法,感興趣的可以了解一下2023-12-12python爬取豆瓣電影排行榜(requests)的示例代碼
這篇文章主要介紹了python爬取豆瓣電影排行榜(requests),本文給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下2021-02-02Python使用win32 COM實現(xiàn)Excel的寫入與保存功能示例
這篇文章主要介紹了Python使用win32 COM實現(xiàn)Excel的寫入與保存功能,結(jié)合實例形式分析了Python調(diào)用win32 COM組件針對Excel文件的讀寫與保存相關(guān)操作技巧,需要的朋友可以參考下2018-05-05Numpy中轉(zhuǎn)置transpose、T和swapaxes的實例講解
下面小編就為大家分享一篇Numpy中轉(zhuǎn)置transpose、T和swapaxes的實例講解,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2018-04-04python3通過udp實現(xiàn)組播數(shù)據(jù)的發(fā)送和接收操作
這篇文章主要介紹了python3通過udp實現(xiàn)組播數(shù)據(jù)的發(fā)送和接收操作,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2020-05-05Django數(shù)據(jù)庫類庫MySQLdb使用詳解
Django項目要操作數(shù)據(jù)庫,首先要和數(shù)據(jù)庫建立連接,才能讓程序中的數(shù)據(jù)和數(shù)據(jù)庫關(guān)聯(lián)起來進(jìn)行數(shù)據(jù)的增刪改查操作。這篇文章主要介紹了Django數(shù)據(jù)庫類庫MySQLdb使用詳解,感興趣的小伙伴們可以參考一下2019-04-04Python3.6實現(xiàn)帶有簡單界面的有道翻譯小程序
本文通過實例代碼給大家介紹了基于Python3.6實現(xiàn)帶有簡單界面的有道翻譯小程序,非常不錯,具有一定的參考借鑒價值,需要的朋友參考下吧2019-04-04