在GUI裏,拖放是指用戶點擊一個虛擬的對象,拖動,而後放置到另一個對象上面的動做。通常狀況下,須要調用不少動做和方法,建立不少變量。python
拖放能讓用戶很直觀的操做很複雜的邏輯。app
通常狀況下,咱們能夠拖放兩種東西:數據和圖形界面。把一個圖像從一個應用拖放到另一個應用上的實質是操做二進制數據。把一個表格從Firefox上拖放到另一個位置 的實質是操做一個圖形組。函數
本例使用了QLineEdit
和QPushButton
。把一個文本從編輯框裏拖到按鈕上,更新按鈕上的標籤(文字)。ui
#!/usr/bin/python3 # -*- coding: utf-8 -*- """ ZetCode PyQt5 tutorial This is a simple drag and drop example. Author: Jan Bodnar Website: zetcode.com Last edited: August 2017 """ from PyQt5.QtWidgets import (QPushButton, QWidget, QLineEdit, QApplication) import sys class Button(QPushButton): def __init__(self, title, parent): super().__init__(title, parent) self.setAcceptDrops(True) def dragEnterEvent(self, e): if e.mimeData().hasFormat('text/plain'): e.accept() else: e.ignore() def dropEvent(self, e): self.setText(e.mimeData().text()) class Example(QWidget): def __init__(self): super().__init__() self.initUI() def initUI(self): edit = QLineEdit('', self) edit.setDragEnabled(True) edit.move(30, 65) button = Button("Button", self) button.move(190, 65) self.setWindowTitle('Simple drag and drop') self.setGeometry(300, 300, 300, 150) if __name__ == '__main__': app = QApplication(sys.argv) ex = Example() ex.show() app.exec_()
class Button(QPushButton): def __init__(self, title, parent): super().__init__(title, parent) self.setAcceptDrops(True)
爲了完成預約目標,咱們要重構一些方法。首先用QPushButton
上構造一個按鈕實例。this
self.setAcceptDrops(True)
激活組件的拖拽事件。spa
def dragEnterEvent(self, e): if e.mimeData().hasFormat('text/plain'): e.accept() else: e.ignore()
首先,咱們重構了dragEnterEvent()
方法。設定好接受拖拽的數據類型(plain text)。code
def dropEvent(self, e): self.setText(e.mimeData().text())
而後重構dropEvent()
方法,更改按鈕接受鼠標的釋放事件的默認行爲。orm
edit = QLineEdit('', self) edit.setDragEnabled(True)
QLineEdit
默認支持拖拽操做,因此咱們只要調用setDragEnabled()
方法使用就好了。對象
程序展現:
繼承
這個例子展現怎麼拖放一個button組件。
#!/usr/bin/python3 # -*- coding: utf-8 -*- """ ZetCode PyQt5 tutorial In this program, we can press on a button with a left mouse click or drag and drop the button with the right mouse click. Author: Jan Bodnar Website: zetcode.com Last edited: August 2017 """ from PyQt5.QtWidgets import QPushButton, QWidget, QApplication from PyQt5.QtCore import Qt, QMimeData from PyQt5.QtGui import QDrag import sys class Button(QPushButton): def __init__(self, title, parent): super().__init__(title, parent) def mouseMoveEvent(self, e): if e.buttons() != Qt.RightButton: return mimeData = QMimeData() drag = QDrag(self) drag.setMimeData(mimeData) drag.setHotSpot(e.pos() - self.rect().topLeft()) dropAction = drag.exec_(Qt.MoveAction) def mousePressEvent(self, e): super().mousePressEvent(e) if e.button() == Qt.LeftButton: print('press') class Example(QWidget): def __init__(self): super().__init__() self.initUI() def initUI(self): self.setAcceptDrops(True) self.button = Button('Button', self) self.button.move(100, 65) self.setWindowTitle('Click or Move') self.setGeometry(300, 300, 280, 150) def dragEnterEvent(self, e): e.accept() def dropEvent(self, e): position = e.pos() self.button.move(position) e.setDropAction(Qt.MoveAction) e.accept() if __name__ == '__main__': app = QApplication(sys.argv) ex = Example() ex.show() app.exec_()
上面的例子中,窗口上有一個QPushButton
組件。左鍵點擊按鈕,控制檯就會輸出press
。右鍵能夠點擊而後拖動按鈕。
class Button(QPushButton): def __init__(self, title, parent): super().__init__(title, parent)
從QPushButton
繼承一個Button
類,而後重構QPushButton
的兩個方法:mouseMoveEvent()
和mousePressEvent()
.mouseMoveEvent()
是拖拽開始的事件。
if e.buttons() != Qt.RightButton: return
咱們只劫持按鈕的右鍵事件,左鍵的操做仍是默認行爲。
mimeData = QMimeData() drag = QDrag(self) drag.setMimeData(mimeData) drag.setHotSpot(e.pos() - self.rect().topLeft())
建立一個QDrag
對象,用來傳輸MIME-based數據。
dropAction = drag.exec_(Qt.MoveAction)
拖放事件開始時,用到的處理函數式start()
.
def mousePressEvent(self, e): QPushButton.mousePressEvent(self, e) if e.button() == Qt.LeftButton: print('press')
左鍵點擊按鈕,會在控制檯輸出「press」。注意,咱們在父級上也調用了mousePressEvent()
方法,否則的話,咱們是看不到按鈕按下的效果的。
position = e.pos() self.button.move(position)
在dropEvent()
方法裏,咱們定義了按鈕按下後和釋放後的行爲,得到鼠標移動的位置,而後把按鈕放到這個地方。
e.setDropAction(Qt.MoveAction) e.accept()
指定放下的動做類型爲moveAction。
程序展現:
這個就一個按鈕,沒啥可展現的,弄GIF太麻煩了。