《快速掌握PyQt5》第十八章 拖放與剪貼簿
第十八章 拖放與剪貼簿
拖放和剪貼簿的功能原理基礎都是QMimeData類,所以這裡我們將這兩種放在一起講。QMimeData當然與MIME相關:MIME是描述訊息內容型別的因特網標準,可以簡單理解為對副檔名的詳細解釋,通過該解釋,程式就可以知道應該以何種方式處理該資料。每個MIME型別由兩部分組成,前面是資料的大類別,後面定義具體的種類,例如副檔名為.png的MIME型別為image/png;而QMimeData則給記錄自身MIME型別的資料提供了一個容器,用於專門處理MIME型別資料。
詳細的MIME型別請參考:MIME參考手冊
針對常見的MIME型別,QMimeData類提供了很方便的函式用於處理MIME型別資料:
18.1 拖放
拖放分為拖動和放下兩個動作,它們涉及到以下事件:
- DragEnterEvent: 所拖動目標進入接收該事件的視窗或控制元件時觸發;
- DragMoveEvent: 所拖動目標進入視窗或控制元件後,繼續被拖動時觸發;
- DragLeaveEvent: 所拖動目標離開視窗或控制元件時觸發;
- DropEvent: 所拖動目標被放下時觸發。
下面我們完成一個可以實現拖放txt檔案並讀取的小程式:
import sys from PyQt5.QtWidgets import QApplication, QTextBrowser class Demo(QTextBrowser): # 1 def __init__(self): super(Demo, self).__init__() self.setAcceptDrops(True) # 2 def dragEnterEvent(self, QDragEnterEvent): # 3 print('Drag Enter') if QDragEnterEvent.mimeData().hasText(): QDragEnterEvent.acceptProposedAction() def dragMoveEvent(self, QDragMoveEvent): # 4 print('Drag Move') def dragLeaveEvent(self, QDragLeaveEvent): # 5 print('Drag Leave') def dropEvent(self, QDropEvent): # 6 print('Drag Drop') # MacOS txt_path = QDropEvent.mimeData().text().replace('file:///', '/') # Linux # txt_path = QDropEvent.mimeData().text().replace('file:///', '/').strip() # Windows # txt_path = QDropEvent.mimeData().text().replace('file:///', '') with open(txt_path, 'r') as f: self.setText(f.read()) if __name__ == '__main__': app = QApplication(sys.argv) demo = Demo() demo.show() sys.exit(app.exec_())
1. 繼承QTextBrowser,也就是說下面來實現該控制元件的拖放事件響應函式;
2. setAcceptDrops(True)方法可以讓該控制元件接收放下(Drop)事件;
3. 當拖動目標進入QTextBrowser的那一剎那,觸發dragEnterEvent事件,在該響應函式中,我們先判斷所拖動目標的MIME型別是否為text/plain,若是的話則呼叫acceptProposedAction()方法來表明可以在QTextBrowser上進行拖放動作;
4. 當目標進入窗體後,如果不放下而是繼續移動的話,則會觸發dragMoveEvent事件;
5. 將進入控制元件後的目標再次拖動到控制元件之外時,就會觸發dragLeaveEvent()事件;
6. 將目標在QTextBrowser中放下後,我們先通過QDropEvent.mimeData().text()方法獲取到該檔案的URI路徑,replace()方法將其中的file:///替換為/,這樣得到的值才是我們想要的本地檔案路徑。最後開啟my.txt檔案進行讀取,並用setText()方法將QTextBrowser的文字設為該my.txt的內容。
注:不同系統使用的路徑寫法也不同,請注意區分。在Linux上獲取的路徑中存在'\r\n'所以用strip()去除。
執行截圖如下,筆者將放在桌面的my.txt檔案拖到程式中,程式顯示my.txt檔案的內容:
18.2 剪貼簿
通常我們在Windows或Linux上使用複製都是按ctrl+c然後按ctrl+v進行貼上(Mac上為command+c和command+v),這其中就涉及到了剪貼簿,當進行復制時,其實是將要複製的內容放到了一個無形的剪貼簿上,要貼上時,再將剪貼簿上的內容放到介面上。
當我們瀏覽CSDN部落格,在碰到程式碼想要複製的時候,右上角會出現一個複製按鈕,點選後就可以將所有程式碼複製到剪貼簿上:
我們用PyQt5來實現下類似功能,程式碼如下:
import sys
from PyQt5.QtWidgets import QApplication, QWidget, QTextEdit, QTextBrowser, QPushButton, QGridLayout
class Demo(QWidget):
def __init__(self):
super(Demo, self).__init__()
self.text_edit = QTextEdit(self)
self.text_browser = QTextBrowser(self)
self.clipboard = QApplication.clipboard() # 1
self.clipboard.dataChanged.connect(lambda: print('Data Changed'))
self.copy_btn = QPushButton('Copy', self) # 2
self.copy_btn.clicked.connect(self.copy_func)
self.paste_btn = QPushButton('Paste', self) # 3
self.paste_btn.clicked.connect(self.paste_func)
self.g_layout = QGridLayout()
self.g_layout.addWidget(self.text_edit, 0, 0, 1, 1)
self.g_layout.addWidget(self.text_browser, 0, 1, 1, 1)
self.g_layout.addWidget(self.copy_btn, 1, 0, 1, 1)
self.g_layout.addWidget(self.paste_btn, 1, 1, 1, 1)
self.setLayout(self.g_layout)
def copy_func(self):
self.clipboard.setText(self.text_edit.toPlainText())
def paste_func(self):
self.text_browser.setText(self.clipboard.text())
if __name__ == '__main__':
app = QApplication(sys.argv)
demo = Demo()
demo.show()
sys.exit(app.exec_())
1. 例項化一個剪貼簿,並將其dataChanged訊號和列印函式連線起來。每當剪貼簿內容發生變化的時候,都會觸發dataChanged訊號。在這裡也就是說每當發生變化,控制檯都會打印出Data Changed;
2. 當點選copy_btn後,槽函式copy_func()就會啟動:
def copy_func(self):
self.clipboard.setText(self.text_edit.toPlainText())
在槽函式中,我們將text_edit中的文字獲取過來並通過setText()方法將其設定為剪貼簿的文字;
3. 當點選paste_btn後,槽函式paste_func()啟動:
def paste_func(self):
self.text_browser.setText(self.clipboard.text())
在槽函式中,我們將text_browser的文字設為剪貼簿的文字。當然該槽函式還有另一種實現方法:
def paste_func(self):
mime = self.clipboard.mimeData()
if mime.hasText():
self.text_browser.setText(mime.text())
首先通過mimeData()方法獲取剪貼簿內容的MIME型別,然後判斷mime型別是否為text/plain,是的話則通過text()方法獲取,並設為text_browser文字。
當然以上只是針對文字內容,當然還可以複製圖片等檔案,而剪貼簿當然也有相應的方法,以下列出常用的:
方法 | 解釋 |
clear() | 清空剪貼簿內容 |
mimeData() | 獲取剪貼簿上的MIME型別資料 |
setMimeData() | 將MIME型別資料放到剪貼簿中 |
pixmap() | 獲取剪貼簿上的QPixmap型別資料 |
setPixmap() | 將QPixmap型別資料放到剪貼簿中 |
image() | 獲取剪貼簿上的QImage型別資料 |
setImage() | 將QImage型別資料放到剪貼簿中 |
text() | 獲取剪貼簿上的文字 |
setText() | 將文字放到剪貼簿中 |
執行截圖如下,在左側出入文字,點選Copy,再點選Paste,右側顯示相應文字:
18.3 小結
1. 使用QMimeData類來處理MIME型別資料;
1. 拖放事件一共有四種,分別在拖動目標進入視窗或部件時、目標進入後繼續被拖動時、目標離開視窗或控制元件時以及目標被放下時;
2. 剪貼簿的內容發生變化的話,則會觸發dataChanged訊號。剪貼簿針對不同資料型別有相應獲取和設定的方法。
----------------------------------------------------------------------
喜歡的小夥伴可以加入這個Python QQ交流群一起學習:820934083