pyQT——拖拽
拖拽
在GUI裡,拖放是指使用者點選一個虛擬的物件,拖動,然後放置到另外一個物件上面的動作。一般情況下,需要呼叫很多動作和方法,建立很多變數。
拖放能讓使用者很直觀的操作很複雜的邏輯。
一般情況下,我們可以拖放兩種東西:資料和圖形介面。把一個影象從一個應用拖放到另外一個應用上的實質是操作二進位制資料。把一個表格從Firefox上拖放到另外一個位置 的實質是操作一個圖形組。
簡單的拖放
本例使用了QLineEdit
和QPushButton
。把一個文字從編輯框裡拖到按鈕上,更新按鈕上的標籤(文字)。
#!/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
上構造一個按鈕例項。
self.setAcceptDrops(True)
啟用元件的拖拽事件。
def dragEnterEvent(self, e):
if e.mimeData().hasFormat('text/plain'):
e.accept()
else:
e.ignore()
首先,我們重構了dragEnterEvent()
方法。設定好接受拖拽的資料型別(plain text)。
def dropEvent(self, e):
self.setText(e.mimeData().text())
然後重構dropEvent()
方法,更改按鈕接受滑鼠的釋放事件的預設行為。
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太麻煩了。