PyQt 获取 DragLeaveEvent 的发送者/来源

问题描述 投票:0回答:2

嗨在PyQt5(PyQt:v 5.15.7)中得到了这段代码,基本上我正在尝试跟踪拖到QMainwindow之外的小部件:

#!/usr/bin/env python3

from PyQt5.QtWidgets import (QApplication, QWidget, QMainWindow, 
                             
                             QVBoxLayout, QPushButton, QGridLayout
                             )
                            
from PyQt5.QtCore import Qt, QMimeData, pyqtSignal, pyqtSlot
from PyQt5.QtGui import QDrag, QPixmap, QCursor

class DragWidget(QWidget):
    
    def __init__(self, *args, name , **kwargs):
        super().__init__(*args, **kwargs)
    
    def mouseMoveEvent(self, e):

        if e.buttons() == Qt.LeftButton:
            drag = QDrag(self)
            mime = QMimeData()
            drag.setMimeData(mime)

            pixmap = QPixmap(self.size())
            self.render(pixmap)
            drag.setPixmap(pixmap)

            drag.exec_(Qt.MoveAction)

class MainWindow(QMainWindow):
    
    
    whereDropped = pyqtSignal(int,int)
    
    dragleaves = pyqtSignal()
    

    def __init__(self):
        super().__init__()
        
        self.setGeometry(200,200, 400, 500)
        
        
        
        self.container = QWidget()
        
        self.layout = QGridLayout()

        self.container.setLayout(self.layout)

        self.setCentralWidget(self.container)
        
        for i in range(4):
            
            self.x = DragWidget(self, name = 'widget_'+str(i))
            
            self.layout.addWidget( self.x)
            
            self.x.setObjectName('widget_'+str(i))
            
            self.b = QPushButton('widget___'+str(i))
            
            
                                    
            
            self.layout_2 = QVBoxLayout()
            
            self.x.setLayout(self.layout_2)
            
            self.layout_2.addWidget(self.b)
            
            
            
            self.x.show()

    
        
        self.installEventFilter(self)
        
        self.setAcceptDrops(True)
        
        self.whereDropped.connect(self.attdeta)
        
        self.dragleaves.connect(self.removeParent)
    
    @pyqtSlot()
    def removeParent(self) :
        
        print("\n\nself.dragleaves.connect(self.removeParent))")
        pass
        
    
    @pyqtSlot(int, int)    
    def attdeta(self, tupx, tupy) :
        
        print("\n\nself.whereDropped.connect(self.attdeta)")
        print('tupxy : ', tupx , tupy)
    
    
    
    def dropEvent(self, e):
        pos = e.pos()
        widget = e.source()
        
        print('\n\ndropEvent _________')
        print('widget = e.source() :' , widget)
        
        print('e.pos()  : ' , pos ,'\n\n')

        
        self.whereDropped.emit(e.pos().x(), e.pos().y())

        e.accept()
    
    def dragEnterEvent(self, e):
        
        print('dragEnterEvent _________' , e.source(), '\n')
        print('dragEnterEvent _________event-source-name :'  ,e.source().objectName())
        
        print('e.pos()  : ' , e.pos().x())
        
        print('e.pos()  : ' , e.pos().y() ,'\n\n')
        
        e.accept()
        
    def dragLeaveEvent(self, event):
        
        print('\n\nDragLeaveEvent event : ', event)
        
        # print(event.sender())  ### AttributeError: 'QDragLeaveEvent' object has no attribute 'sender'
      
        # print(event.source()) ### AttributeError: 'QDragLeaveEvent' object has no attribute 'source'

        print("Drag left at: " + str(self.mapFromGlobal(QCursor.pos())))     
        
        
        print('self.dragleaves.emit()')
        self.whereDropped.emit(self.mapFromGlobal(QCursor.pos()).x(), self.mapFromGlobal(QCursor.pos()).y()) ## see [https://stackoverflow.com/questions/50022465/how-do-i-get-the-exit-point-from-a-qdragleaveevent][1]
        
        self.dragleaves.emit()
        
        event.accept()


app = QApplication([])
w = MainWindow()
w.show()

app.exec_()

有机会获得

dragLeaveEvent
的发件人/来源/小部件,例如

dragEnterEvent
??? :

def dragEnterEvent(self, e):
        
        print('dragEnterEvent _________' , e.source(), '\n')
        print('dragEnterEvent _________event-source-name :'  ,e.source().objectName())
        
        print('e.pos()  : ' , e.pos().x())
        
        print('e.pos()  : ' , e.pos().y() ,'\n\n')
        
        e.accept()
python qt pyqt pyqt5
2个回答
1
投票

由于

QDragLeaveEvent
前面始终带有
QDragEnterEvent
,因此您可以将源小部件存储在
dragEnterEvent()
中并在
dragLeaveEvent()
中使用它。

所以,就这样做吧。

...
    def dragEnterEvent(self, e):
        self.drag_source = e.source()
        ...
        
    def dragLeaveEvent(self, event):
        print('dragLeaveEvent, drag_source:', self.drag_source)
        ...
...

0
投票

所以我添加这段代码来完成上面的答案,因为只使用:

...
    def dragEnterEvent(self, e):
        self.drag_source = e.source()
        ...
        
    def dragLeaveEvent(self, event):
        print('dragLeaveEvent, drag_source:', self.drag_source)
        ...

当我需要处理多个子 Widget 并需要能够将其放回原来的布局时,这是不够的。我需要在字典中存储一些小部件信息。实际上,我需要存储拖动的 Widget 的父级,以便能够将其重新添加到其原始父级,并在重新设置其父级时将其添加到其原始布局。

from PyQt5.QtCore import QT_VERSION_STR, PYQT_VERSION_STR
print("Qt: v", QT_VERSION_STR, "\tPyQt: v", PYQT_VERSION_STR)

from PyQt5.QtWidgets import (QApplication, QWidget, QMainWindow,                            
                             QVBoxLayout, QPushButton)
                            
from PyQt5.QtCore import Qt, QMimeData, QEvent, QObject
from PyQt5.QtGui import QDrag, QPixmap

class DragWidget(QWidget):
    
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        
        self.setWindowTitle(self.objectName())
        
        self.installEventFilter(self)
        
        self.drag_source = drag_source
        
        self.mouseMoveEvent = self.mouseMoveEventNEW
        
    
    def eventFilter(self, source, event):
                
        if type(source) == DragWidget :
            
            if event.type() == QEvent.Close:
                
                source.setParent(self.drag_source[source])
                
                name_wid = self.objectName()
                
                lay_inter = self.parent().parent().findChildren( QVBoxLayout , 'lay_'+name_wid.rsplit('_')[-1])
                            
                source.mouseMoveEvent = self.mouseMoveEventNEW
                
                lay_inter[0].addWidget(self)
                
                self.drag_source.pop(source)
                
                event.ignore()
                
                return True
                
            else:
                return QObject.eventFilter(self, source, event)
            
        else:
            
            return False    
    
    def mouseMoveEventPASS(self):
        
        pass
         
    def mouseMoveEventNEW(self, e):

        if e.buttons() == Qt.LeftButton:
            drag = QDrag(self)
            mime = QMimeData()
            drag.setMimeData(mime)

            pixmap = QPixmap(self.size())
            self.render(pixmap)
            drag.setPixmap(pixmap)

            drag.exec_(Qt.MoveAction)

class MainWindow(QMainWindow):    

    def __init__(self, *args, **kwargs):
        super().__init__()
        
        self.setGeometry(600,200, 400, 500)
        
        self.container = QWidget()
        
        self.container.setObjectName('pippopippo')
        
        self.layout = QVBoxLayout()
        
        self.layout.setObjectName('pippopippopippo')

        self.container.setLayout(self.layout)

        self.setCentralWidget(self.container)
        
        for i in range(4):
            
            self.layout2 = QVBoxLayout()
            
            self.layout2.setObjectName('lay_'+str(i))
            
            self.widg = QWidget()
            
            self.widg.setStyleSheet("""                                  
                                        background-color: yellow; 
                                        border: 5px dashed black;                         
                                """)
            
            self.widg.setLayout(self.layout2)
            
            self.widg.setObjectName('bigger_widg_'+str(i))
            
            self.layout.addWidget(self.widg)
            
            self.x = DragWidget(self, objectName = 'widget_'+str(i))
            
            self.layout2.addWidget( self.x)
            
            self.b = QPushButton(self.x.objectName())
            
            self.b.setStyleSheet("""
                                    QPushButton {
                                        background-color: red; 
                                        border: 5px solid black;
                                    }
                                    QPushButton:hover {
                                        color: yellow;
                                        background-color : green;
                                    }
                                """)
            
            self.layout_2 = QVBoxLayout()
            
            self.x.setLayout(self.layout_2)
            
            self.layout_2.addWidget(self.b)
            
        self.setAcceptDrops(True)
        
        self.drag_source = drag_source
        
    
    def dropEvent(self, e):
        
        e.accept()
    
    def dragEnterEvent(self, e):
        
        self.drag_source[e.source()] =  e.source().parent()
        
        e.accept()
        
    def dragLeaveEvent(self, event):       
        
        list(self.drag_source)[-1].setParent(None)
        
        list(self.drag_source)[-1].show()
        
        list(self.drag_source)[-1].setGeometry(50,50, 250,250)
        
        event.accept()
        
        list(self.drag_source)[-1].mouseMoveEvent = DragWidget.mouseMoveEventPASS
 
    def closeEvent(self, event):

        for window in QApplication.topLevelWidgets():
              
            window.close()
           

if __name__ == "__main__":
    
    drag_source = {}

    app = QApplication([])
    
    w = MainWindow()
    
    w.setObjectName('Name_Main-window')
    
    w.setWindowTitle(w.objectName())
    
    w.show()

    app.exec_()

我还不喜欢

PyQt QDockWidget
https://doc.qt.io/qtforpython-5/PySide2/QtWidgets/QDockWidget.html);我很快就会看看它们。

这里有一张图片,描述了我的代码的输出:

© www.soinside.com 2019 - 2024. All rights reserved.