背景
在Mac版的百度云盘上有这样一个效果,拖拽一个文件过来,将会显示边框蓝色非常醒目的提醒了操作者。本文介绍用PyQt5监听鼠标的拖拽事件,实现一个类似的效果,当拖拽时动态的改变整个界面边框颜色.下面先上源码,共两个文件。一个是入口的main.py文件,一个是自己写的MainWidget.
源码
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
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(
"MainWidget{border:3px solid #165E23}")
else:
self.setStyleSheet(
'')
def dragEnterEvent(self, event):
if event.mimeData().hasUrls():
event.acceptProposedAction()
self.enableBorder(
True)
else:
event.ignore()
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
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(
"MainWidget{border: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