【问题标题】:PyQt Drop Event without subclassing?没有子类化的 PyQt Drop 事件?
【发布时间】:2013-08-02 20:12:02
【问题描述】:

这个 python pyqt 代码按我的意图工作。 但是,我不喜欢将 QLineEdit 子类化,这样我就可以检测到文件拖放到我的 QLineEdit 字段上。我喜欢更优雅、更简单的“连接”技术(新型信号/插槽处理),我用它来检测编辑字段的文本更改。

我的问题:是否有一个信号/插槽连接解决方​​案来处理编辑字段上的滴,而不必继承 QLineEdit?

另外,我必须在子类中实现这两种方法很烦人... dragEnterEvent 和 dropEvent 才能使 drop 工作!

import sys
from PyQt4 import QtGui, QtCore

class dropedit(QtGui.QLineEdit):   # subclass 
    def __init__(self, parent=None):
        super(dropedit, self).__init__(parent)
        self.setDragEnabled(True)
        self.setAcceptDrops(True)

    def dragEnterEvent(self, event):
        print "dragEnterEvent:"

        if event.mimeData().hasUrls():
            event.accept()   # must accept the dragEnterEvent or else the dropEvent can't occur !!!
        else:
            event.ignore()

    def dropEvent(self, event):

        if event.mimeData().hasUrls():   # if file or link is dropped

            urlcount = len(event.mimeData().urls())  # count number of drops

            url = event.mimeData().urls()[0]   # get first url

            self.setText(url.toString())   # assign first url to editline

            #event.accept()  # doesnt appear to be needed

class testDialog(QtGui.QDialog):
    def __init__(self, parent=None):
        super(testDialog, self).__init__(parent)


        form = QtGui.QFormLayout()
        form.setHorizontalSpacing(0)

        myedit = dropedit()
        form.addWidget(myedit)

        self.setLayout(form)
        self.setGeometry(300, 300, 400, 0)
        self.setWindowTitle('drop test')

        myedit.textChanged.connect(self.editchange)   # new style signal slot connections

    @QtCore.pyqtSlot(str)   # int represent the column value
    def editchange(self,data):
        print "editchange:", data

if __name__ == "__main__":

    app = QtGui.QApplication([])
    dl = testDialog()
    dl.exec_()
    sys.exit(app.closeAllWindows())

【问题讨论】:

    标签: python pyqt pyqt4


    【解决方案1】:

    无需子类化:您可以使用事件过滤器:

    import sys
    from PyQt4 import QtGui, QtCore
    
    class testDialog(QtGui.QDialog):
        def __init__(self, parent=None):
            super(testDialog, self).__init__(parent)
    
            form = QtGui.QFormLayout()
            form.setHorizontalSpacing(0)
    
            self.myedit = QtGui.QLineEdit()
            self.myedit.setDragEnabled(True)
            self.myedit.setAcceptDrops(True)
            self.myedit.installEventFilter(self)
    
            form.addWidget(self.myedit)
    
            self.setLayout(form)
            self.setGeometry(300, 300, 400, 0)
            self.setWindowTitle('drop test')
    
            self.myedit.textChanged.connect(self.editchange)   # new style signal slot connections
    
        @QtCore.pyqtSlot(str)   # int represent the column value
        def editchange(self,data):
            print "editchange:", data.toLatin1()
    
        def eventFilter(self, object, event):
            if (object is self.myedit):
                if (event.type() == QtCore.QEvent.DragEnter):
                    if event.mimeData().hasUrls():
                        event.accept()   # must accept the dragEnterEvent or else the dropEvent can't occur !!!
                        print "accept"
                    else:
                        event.ignore()
                        print "ignore"
                if (event.type() == QtCore.QEvent.Drop):
                    if event.mimeData().hasUrls():   # if file or link is dropped
                        urlcount = len(event.mimeData().urls())  # count number of drops
                        url = event.mimeData().urls()[0]   # get first url
                        object.setText(url.toString())   # assign first url to editline
                        #event.accept()  # doesnt appear to be needed
                return False # lets the event continue to the edit
            return False
    
    if __name__ == "__main__":
    
        app = QtGui.QApplication([])
        dl = testDialog()
        dl.exec_()
        sys.exit(app.closeAllWindows())
    

    【讨论】:

    • 哇!有趣的方法,但我希望简化并减少所需的代码量。谢谢你的努力。我可能会在其他地方找到这种方法的用途。
    • @panofish:你的意思是你想避免eventFiltercode?​​span>
    • 我认为需要在accept() 之后返回True。并且根本不需要ignore()
    【解决方案2】:

    我今天遇到了同样的问题,并且能够以不同的(也许不那么正统)的方式解决它。 因此,还可以将 dropEvent 函数从树重新映射到另一个名称,无论是在实例内部还是到拥有该实例的类,并为 dropEvent 分配一个新的自定义函数。这个新函数可以调用或不调用原来的函数,这取决于您是要保留一些功能,还是只重写所有内容。 这是一个sn-p:

    import sys
    from PyQt5.QtWidgets import QTreeView
    from PyQt5.QtGui import QDropEvent
    
    class Demo: 
    
        def __init__(self):
            self.tree = QTreeView()
            self.tree.setDragEnabled(True)
            self.tree.setAcceptDrops(True)
            self.tree.original_dropEvent = self.dataView.dropEvent
            self.tree.dropEvent = self._dataview_dropevent
    
        def _tree_dropevent(self, event: QDropEvent):
            # do stuff ...
            self.tree.original_dropEvent(event)
            # maybe more stuff ..
    

    .

    【讨论】:

      猜你喜欢
      • 2012-10-05
      • 1970-01-01
      • 2010-12-22
      • 2016-11-07
      • 1970-01-01
      • 2011-04-18
      • 2021-12-29
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多