退出时PySide崩溃(使用QCompleter)

时间:2014-01-27 11:58:48

标签: pyside qcompleter

我使用PySide从Qt文档中复制了“自定义完成示例” (Python 2.7.3,PySide 1.1.2,Qt 4.8.1)。

我遇到一个问题,即在退出时抛出win32异常(或在Mac OS X上抛出访问冲突异常)。 在Mac上,我可以看到堆栈跟踪,并且在垃圾收集期间会出现问题,其中对QObject的引用显然不一致,这样情况就会变坏。

我可以使用以下自包含脚本看到此崩溃,仅在接受完成者插入时才会看到。即输入前几个字母,然后接受完成。

另一方面,如果我看到完成列表弹出,但未接受完成,则退出时不会发生崩溃。

################################################################################
# Completer.py
#
# A PySide port of the Qt 4.8 "Custom Completer Example"
# http://qt-project.org/doc/qt-4.8/tools-customcompleter.html
#
################################################################################

from PySide.QtCore import *
from PySide.QtGui import *

class TextEdit(QPlainTextEdit):

    def __init__(self, parent=None):
        super(TextEdit, self).__init__(parent)
        self.c = None

    def completer(self):
        return self.c

    def setCompleter(self, completer):
        if self.c:
            QObject.disconnect(self.c, 0, self, 0)

        self.c = completer

        if not self.c:
            return

        self.c.setWidget(self)
        self.c.setCompletionMode(QCompleter.PopupCompletion)
        self.c.setCaseSensitivity(Qt.CaseInsensitive)
        self.c.activated.connect(self.insertCompletion)

    def insertCompletion(self, completion):
        if self.c.widget() is not self:
            return
        tc = self.textCursor()
        extra = len(completion) - len(self.c.completionPrefix())
        tc.movePosition(QTextCursor.Left)
        tc.movePosition(QTextCursor.EndOfWord)
        tc.insertText(completion[-extra:])
        self.setTextCursor(tc)

    def textUnderCursor(self):
        tc = self.textCursor()
        tc.select(QTextCursor.WordUnderCursor)
        return tc.selectedText()

    def focusInEvent(self, event):
        if self.c:
            self.c.setWidget(self)
        super(TextEdit, self).focusInEvent(event)

    def keyPressEvent(self, e):
        if self.c and self.c.popup().isVisible():
            if e.key() in (Qt.Key_Enter, 
                           Qt.Key_Return,
                           Qt.Key_Escape,
                           Qt.Key_Tab,
                           Qt.Key_Backtab):
                e.ignore()
                return

        # Check for the shortcut combination Ctrl+E
        isShortcut = (e.modifiers() & Qt.ControlModifier) and e.key() == Qt.Key_E
        # Do not process the shortcut when we have a completion
        if not self.c or not isShortcut:
            super(TextEdit, self).keyPressEvent(e)

        noText = not e.text()
        ctrlOrShift = e.modifiers() & (Qt.ControlModifier | Qt.ShiftModifier)
        if not self.c or (ctrlOrShift and noText):
            return

        eow = "~!@#$%^&*()_+{}|:\"<>?,./;'[]\\-=" # End of word
        hasModifier = (e.modifiers() != Qt.NoModifier) and not ctrlOrShift
        completionPrefix = self.textUnderCursor()

        if not isShortcut and \
           (hasModifier or noText or len(completionPrefix) < 1 or e.text()[-1:] in eow):
            self.c.popup().hide()
            return

        if completionPrefix != self.c.completionPrefix():
            self.c.setCompletionPrefix(completionPrefix)
            self.c.popup().setCurrentIndex( self.c.completionModel().index(0,0) )

        cr = self.cursorRect()
        cr.setWidth(self.c.popup().sizeHintForColumn(0) + \
                    self.c.popup().verticalScrollBar().sizeHint().width())
        self.c.complete(cr)


class Completer(QMainWindow):

    words = ("one",
             "two",
             "three",
             "four")

    def __init__(self, parent=None):
        super(Completer, self).__init__(parent)


        self.setWindowTitle("Completer")
        self.textEdit = TextEdit()
        self.completer = QCompleter(self)
        self.completer.setModelSorting(QCompleter.CaseInsensitivelySortedModel)
        self.completer.setCaseSensitivity(Qt.CaseInsensitive)
        self.completer.setWrapAround(False)
        self.completer.setModel(QStringListModel(Completer.words, self.completer))
        self.textEdit.setCompleter(self.completer)

        self.setCentralWidget(self.textEdit)
        self.resize(500, 300)
        self.setWindowTitle("Completer")


if __name__ == '__main__':
    import sys
    from PySide.QtGui import QApplication

    app = QApplication(sys.argv)
    window = Completer()
    window.show()    
    sys.exit(app.exec_())

0 个答案:

没有答案