《快速掌握PyQt5》第十八章 拖放与剪贴板

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/La_vie_est_belle/article/details/82731848

第十八章 拖放与剪贴板

18.1 拖放

18.2 剪贴板

18.3 小结


拖放和剪贴板的功能原理基础都是QMimeData类,所以这里我们将这两种放在一起讲。QMimeData当然与MIME相关:MIME是描述消息内容类型的因特网标准,可以简单理解为对文件扩展名的详细解释,通过该解释,程序就可以知道应该以何种方式处理该数据。每个MIME类型由两部分组成,前面是数据的大类别,后面定义具体的种类,例如扩展名为.png的MIME类型为image/png;而QMimeData则给记录自身MIME类型的数据提供了一个容器,用于专门处理MIME类型数据。

详细的MIME类型请参考:MIME参考手册

针对常见的MIME类型,QMimeData类提供了很方便的函数用于处理MIME类型数据:

判断函数

获取函数

设置函数

MIME 类型

hasText()

text()

setText()

text/plain

hasHtml()

html()

setHtml()

text/html

hasUrls()

urls()

setUrls()

text/uri-list

hasImage()

imageData()

setImageData()

image/ *

hasColor()

colorData()

setColorData()

application/x-color

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

猜你喜欢

转载自blog.csdn.net/La_vie_est_belle/article/details/82731848