【问题标题】:`QTextEdit` cursor becomes frozen after overriding its `dropEvent``QTextEdit` 光标在覆盖其 `dropEvent` 后被冻结
【发布时间】:2015-04-05 10:31:13
【问题描述】:

在一个程序中,我想接受将文件拖放到QTextExit 中以便编辑它的某些部分。

拖放工作正常,但是在将文件拖放到QTextEdit 后,QTextEdit 的光标会冻结(停止闪烁并且无法再移动)。

这是一个最小的例子:

拖放后: (d&d 工作正常,但光标冻结)

我可以在 textEdit 中编辑内容,但在 textEdit 失去焦点后光标仍然可见。

代码:

# -*- coding: utf-8 -*-
import sys
from PyQt5 import Qt

if __name__ == '__main__':
    Application = Qt.QApplication(sys.argv)
    from Drag_drop_window import Ui_Form # import QtDesigner file

class override_textEdit(Qt.QTextEdit):  # override drop event for QTextEdit
    drop_accepted_signal = Qt.pyqtSignal(str) # the signal sends the file name to other widget
    def __init__(self):
        super(override_textEdit,self).__init__()
        self.setText("123")
        self.setAcceptDrops(True)

    def dropEvent(self, event):
        if len(event.mimeData().urls())==1: # accept event when only one file was dropped
            event.accept()
            self.drop_accepted_signal.emit(event.mimeData().urls()[0].toLocalFile())

        else:
            Qt.QMessageBox.critical(self,"Accept Single File Only","Accept Single File Only",Qt.QMessageBox.Abort)

            event.ignore()

class myWidget(Qt.QWidget):
    def __init__(self):
        super(myWidget, self).__init__()
        self.main = Ui_Form()
        self.main.setupUi(self)

        self.main.textEdit = override_textEdit()
        self.main.verticalLayout.addWidget(self.main.textEdit)
        self.main.textEdit.drop_accepted_signal.connect(self.slot)

        self.show()

    def slot(self,filename):
        self.main.lineEdit.setText(filename) # display file name in lineEdit



if __name__ == '__main__':
    my_Qt_Program = myWidget()

    my_Qt_Program.show()
    sys.exit(Application.exec_())

QtDesigner生成的Drag_drop_window.py

# -*- coding: utf-8 -*-

# Form implementation generated from reading ui file 'Drag_drop_window.ui'
#
# Created: Sun Apr  5 17:53:03 2015
#      by: PyQt5 UI code generator 5.3.2
#
# WARNING! All changes made in this file will be lost!

from PyQt5 import QtCore, QtGui, QtWidgets

class Ui_Form(object):
    def setupUi(self, Form):
        Form.setObjectName("Form")
        Form.resize(400, 300)
        self.verticalLayout = QtWidgets.QVBoxLayout(Form)
        self.verticalLayout.setObjectName("verticalLayout")
        self.lineEdit = QtWidgets.QLineEdit(Form)
        self.lineEdit.setObjectName("lineEdit")
        self.verticalLayout.addWidget(self.lineEdit)

        self.retranslateUi(Form)
        QtCore.QMetaObject.connectSlotsByName(Form)

    def retranslateUi(self, Form):
        _translate = QtCore.QCoreApplication.translate
        Form.setWindowTitle(_translate("Form", "Form"))

【问题讨论】:

    标签: python python-3.x pyqt pyqt5


    【解决方案1】:

    我发现将以下四行添加到 dropEvent 的末尾可以使事情正常进行:

            mimeData = QtCore.QMimeData()
            mimeData.setText("")
            dummyEvent = QtGui.QDropEvent(event.posF(), event.possibleActions(),
                    mimeData, event.mouseButtons(), event.keyboardModifiers())
    
            super(override_textEdit, self).dropEvent(dummyEvent)
    

    您已经覆盖了QTextEdit 控件的dropEvent 方法,但您没有调用被覆盖的超类方法。我猜想在被覆盖的方法中有一些清理代码需要运行才能解决您在使用游标时遇到的问题。但是,只需使用 drop 事件调用超类方法,即

            super(override_textEdit, self).dropEvent(event)
    

    没有做你希望的事情。这会将拖放文件的 URL 输入到文本编辑控件中。

    我没有发现在调用超类dropEvent 之前调用accept()ignore()setDropAction(Qt.IgnoreAction) 的任何组合有任何效果。我怀疑超类方法自己决定是接受还是忽略该事件,这可能会覆盖您的子类所做的事情。

    因此,我创建了一个“假”拖放事件,与收到的事件相同,只是文本数据为空,并将这个假事件传递给超类。当然,如果超类愿意,欢迎在某处插入这个空文本,但如果这样做,它不会有任何效果。

    【讨论】:

      猜你喜欢
      • 2021-05-18
      • 2019-04-05
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-04-20
      • 1970-01-01
      相关资源
      最近更新 更多