PyQt5学习记录---监听鼠标拖拽事件实现Mac上百度云盘拖拽效果

Posted yanzi1225627

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了PyQt5学习记录---监听鼠标拖拽事件实现Mac上百度云盘拖拽效果相关的知识,希望对你有一定的参考价值。

背景

在Mac版的百度云盘上有这样一个效果,拖拽一个文件过来,将会显示边框蓝色非常醒目的提醒了操作者。本文介绍用PyQt5监听鼠标的拖拽事件,实现一个类似的效果,当拖拽时动态的改变整个界面边框颜色.下面先上源码,共两个文件。一个是入口的main.py文件,一个是自己写的MainWidget.

源码

widgets.py

# coding=utf-8

from PyQt5.QtWidgets import QApplication, QMainWindow, QTextEdit, QDockWidget, QListWidget, QWidget, QLineEdit, QDateTimeEdit, QVBoxLayout, QHBoxLayout \\
        , QGridLayout, QLabel, QFrame
from PyQt5.QtCore import Qt, QDateTime, QMimeData, QUrl

# 应用程序的主Widget
class MainWidget(QFrame):
    def __init__(self):
        super().__init__()
        self.initUI()

    def initUI(self):
        vlayout = QVBoxLayout()
        grid = QGridLayout()
        label1 = QLabel('文件路径')
        self.lineEdit = QLineEdit()
        self.lineEdit.setFixedHeight(40)
        grid.addWidget(label1, 0, 0)
        grid.addWidget(self.lineEdit, 0, 1, )
        vlayout.addLayout(grid)
        vlayout.addStretch(1)
        self.setLayout(vlayout)
        self.setAcceptDrops(True)

    def enableBorder(self, enable):
        if enable:
            # self.setStyleSheet("MainWidgetborder:3px solid green")
            self.setStyleSheet("MainWidgetborder:3px solid #165E23")
        else:
            self.setStyleSheet('')

    def dragEnterEvent(self, event):
        if event.mimeData().hasUrls():
            event.acceptProposedAction()
            self.enableBorder(True)
        else:
            event.ignore()
            # super(self).dragEnterEvent(event)

    def dragMoveEvent(self, event):
        if event.mimeData().hasUrls():
            event.setDropAction(Qt.LinkAction)
            event.accept()
        else:
            event.ignore()

    def dragLeaveEvent(self, event):
        print('dragLeaveEvent...')
        self.enableBorder(False)

    def dropEvent(self, event):
        if event.mimeData().hasUrls():
            # 遍历输出拖动进来的所有文件路径
            for url in event.mimeData().urls():
                path = url.toLocalFile()
                print(path)
            text = event.mimeData().text()
            self.lineEdit.setText(text)
            event.acceptProposedAction()
            self.enableBorder(False)
        else:
            event.ignore()

main.py

# coding=utf-8

import sys
from PyQt5.QtWidgets import QApplication, QMainWindow, QTextEdit, QDockWidget, QListWidget
from widgets import  MainWidget

class MainWindow(QMainWindow):
    def __init__(self):
        super().__init__()
        self.init()


    def init(self):
        self.text = QTextEdit('主窗口')
        self.widget = MainWidget()
        self.setCentralWidget(self.widget)
        self.setGeometry(200, 200, 800, 400)
        self.setWindowTitle('监听拖拽')
        self.show()


def main():
    app = QApplication(sys.argv)
    window = MainWindow()
    sys.exit(app.exec_())



# 入口
if __name__ == '__main__':
    main()

运行效果

要点提示

1.如何监听拖拽

其实也比较简单,首先需要在被触发的对象里通过self.setAcceptDrops(True)来打开开关。本例我们直接在MainWidget里打开这个开关,表示只要拖到这个Widget上都会触发事件。
然后就是要对下面这四个函数进行重写:

def dragEnterEvent(self, event)
def dragMoveEvent(self, event):
def dragLeaveEvent(self, event):
def dropEvent(self, event):

其中的dragEnterEvent是进入到Widget时触发的一定要重写。dragMoveEvent有没有都无所谓,在这里我们通过event.setDropAction(Qt.LinkAction)有了这句话后,才看到上面截图里的链接两个字,如果不修改的话默认的是复制两个字。在dragLeaveEvent里,我们触发恢复正常的边框事件。在dropEvent里表示鼠标在Widget区域松开了,在这里打印鼠标拖拽的东西。

       for url in event.mimeData().urls():
                path = url.toLocalFile()
                print(path)
            text = event.mimeData().text()
            self.lineEdit.setText(text)
            event.acceptProposedAction()
            self.enableBorder(False)

从中可以看到通过urls()text()这两个函数取出来的东西是不一样的,前者是一个QUrl的数组,后者是一个纯字符串。大家可以根据需要使用。

3.如何修改边框

通过下面这个函数实现:

    def enableBorder(self, enable):
        if enable:
            # self.setStyleSheet("MainWidgetborder:3px solid green")
            self.setStyleSheet("MainWidgetborder:3px solid #165E23")
        else:
            self.setStyleSheet('')

注意:这里我们的MainWidget继承的是QFrame而不是QWidget,如果是QWidget设QSS是没有效果的!实际上QFrame是QWidget的子类,而QLable和QPushButton等是QFrame的子类。所以我们这里把父类改成QFrame是没有什么关系的。

4.QSS的使用

关于QSS暂时不多讲,附三个官方链接和1个demo就足够用了。
1. http://doc.qt.io/qt-5/stylesheet-reference.html
2. http://doc.qt.io/qt-5/stylesheet-syntax.html
3. http://doc.qt.io/qt-5/stylesheet-examples.html
4. https://github.com/pyqt/examples/tree/master/widgets/stylesheet/qss

缺憾

唯一的缺憾是鼠标拖过来的时候,鼠标上的链接两字无法做到控制,暂时没找到解决方法。有知道的请告知。

本文系原创,转载请注明作者yanzi1225627

以上是关于PyQt5学习记录---监听鼠标拖拽事件实现Mac上百度云盘拖拽效果的主要内容,如果未能解决你的问题,请参考以下文章

实现拖拽的原理

jQuery 实现DOM元素拖拽交换位置

十三周学习总结

Mac 鼠标/键盘事件的监听和模拟

js 实现拖拽元素

PyQt5学习记录---实战:监听系统粘贴板并提取时间