[PyQt] QCompleter with any data Model will cause Segmentation fault in pyQt4?

^_^Sisyphus^_^ freesisyphuswang at gmail.com
Tue Dec 25 12:46:04 GMT 2012


Dear all,

I create *QCompleter*s for *QLineEdit*, which work fine if there is no
dynamically defined function/method in the subclasses (try to run the
script with *./bugCompleterFilesysModel.py n* n in [0, 1, 2, 9], then try
to bring up the completer by deleting some char in the LineEdit box). The
QCompleter can work with *QStringList*, *QStringListModel*, and *
QFileSystemModel*.

If I add some dynamically defined function/method in the subclass with
QCompleter of simple *QStringList*, the instances work fine too (try to run
the script with *./bugCompleterFilesysModel.py* n n in [10, 20, 30], then
try to bring up the completer by deleting some char in the LineEdit box).

However, if I defined any function/method dynamically, the QCompleter with
any kind of *data model*, will *raise an error* during closing the GUI
window:

QObject::startTimer: QTimer can only be used with threads started with
QThreadSegmentation fault


To repeat the error, try to run the script with *./bugCompleterFilesysModel.py
mn* m in [1,2,3], n in [1, 2, 9], then try to bring up the completer by
deleting some char in the LineEdit box, then close the window.

Can anyone tell my why is that and how to fix it? I have been scratching my
head for hours.

Thanks ahead!

Full script of *bugCompleterFilesysModel.py*:

#!/usr/bin/env python# -*- coding: UTF-8 -*-class MyBaseWidget(QtGui.QWidget):
    dirChanged=QtCore.pyqtSignal(QtCore.QString)
    def __init__(self,parent=None,addfunc0=False,*args,**kwargs):
        super(MyBaseWidget, self).__init__(parent)
        self.addfunc0=addfunc0
        self.func0=None
        self.dummyWgt=1
        self.initUI()

    def initUI(self,*args,**kwargs):
        addfunc0=self.addfunc0
        if addfunc0 == 1:
            self.func0=self.funcFactory0('1')
            _func0str="self.funcFactory0('1')"
        if addfunc0 == 2:
            self.func0=self.funcFactory1('1')
            _func0str="self.funcFactory1('1')"
        if addfunc0 == 3:
            self.func0=self.funcFactory1b()
            _func0str="self.funcFactory1b()"

        if addfunc0 > 0:
            #print self.printWgt
            print 'use %s as func0'%(_func0str)
            print 'self.func0 = %s'%(self.func0)
            self.func0()

        self.show()

    def printWgt(self,wgt0):
        print 'Input obj is:', wgt0.__class__.__name__

    def funcFactory0(self,wgt0):
        def _func():
            self.printWgt(wgt0)
        return _func

    def funcFactory1(self,wgt0):
        import types
        def _func(self):
            self.printWgt(wgt0)
        return types.MethodType(_func,self,mainWidget)

    def funcFactory1b(self):
        import types
        def _func(self):
            self.printWgt(self.dummyWgt)
        return types.MethodType(_func,self,mainWidget)

class StringWidget(MyBaseWidget):
    dirChanged=QtCore.pyqtSignal(QtCore.QString)
    def initUI(self,*args,**kwargs):
        currdir=r'/tmp'
        self.currdir=currdir
        self._tb=[]


        completer=QtGui.QCompleter(QtCore.QStringList(['/tmp/'+i for i
in 'abcdefg']), parent=self)
        completer.setMaxVisibleItems(5)
        self.completer=completer

        _tb=QtGui.QLineEdit(currdir)
        _tb.setCompleter(completer)

        theLayout=QtGui.QHBoxLayout(self)
        theLayout.addWidget(_tb)
        self._tb=_tb

        MyBaseWidget.initUI(self,*args,**kwargs)
class StringModelWidget(MyBaseWidget):
    dirChanged=QtCore.pyqtSignal(QtCore.QString)
    def initUI(self,*args,**kwargs):
        currdir=r'/tmp'
        self.currdir=currdir
        self._tb=[]

        fsModel=QtGui.QStringListModel(['/tmp/'+i for i in 'abcdefg'])
        self.fsModel=fsModel
        #self.fsModel.setParent(self)

        completer=QtGui.QCompleter()
        completer.setMaxVisibleItems(5)
        completer.setModel(fsModel)
        self.fsModel.setParent(completer)
        self.completer=completer

        _tb=QtGui.QLineEdit(currdir)
        _tb.setCompleter(completer)

        theLayout=QtGui.QHBoxLayout(self)
        theLayout.addWidget(_tb)
        self._tb=_tb

        MyBaseWidget.initUI(self,*args,**kwargs)


class FileModelWidget(MyBaseWidget):
    dirChanged=QtCore.pyqtSignal(QtCore.QString)

    def initUI(self,*args,**kwargs):
        currdir=r'/tmp'
        self.currdir=currdir
        self._tb=[]

        fsModel=QtGui.QFileSystemModel(parent=self)
        fsModel.setRootPath('')
        fsModel.setFilter(QtCore.QDir.AllDirs|QtCore.QDir.Dirs)
        self.fsModel=fsModel
        #self.fsModel.setParent(self)

        completer=QtGui.QCompleter(parent=self)
        completer.setMaxVisibleItems(5)
        completer.setModel(fsModel)
        self.fsModel.setParent(completer)
        self.completer=completer

        _tb=QtGui.QLineEdit(currdir)
        _tb.setCompleter(completer)

        theLayout=QtGui.QHBoxLayout(self)
        theLayout.addWidget(_tb)
        self._tb=_tb

        MyBaseWidget.initUI(self,*args,**kwargs)

class mainWidget(MyBaseWidget):

    def initUI(self,*args,**kwargs):

        self.mainLayout=QtGui.QVBoxLayout(self)
        self.wgts=[]

        _wgt0=StringWidget(self)
        self.wgts.append(_wgt0)

        _wgt1=StringModelWidget(self)
        self.wgts.append(_wgt1)


        _wgt2=FileModelWidget()
        self.wgts.append(_wgt2)


        for _w in self.wgts:
            print _w
            self.mainLayout.addWidget(_w)
        MyBaseWidget.initUI(self,*args,**kwargs)
def main():
    app = QtGui.QApplication(sys.argv)
    argv=sys.argv
    mainWgt = None
    if len(argv)>1:
        nwgt = int(sys.argv[1])
        _addfunc0=nwgt/10
        _nwgt=nwgt-_addfunc0*10
        print _nwgt,_addfunc0
        if _nwgt == 0:
            _MainWgt=StringWidget


        if _nwgt == 1:
            _MainWgt=StringModelWidget

        if _nwgt == 2:
            _MainWgt=FileModelWidget

        if _nwgt == 9:
            _MainWgt=mainWidget
        print 'use %s as main widget'%(_MainWgt.__name__)
        mainWgt=_MainWgt(addfunc0=_addfunc0)
    else:
        mainWgt = mainWidget(addfunc0=0)



    if mainWgt:
        sys.exit(app.exec_())
if __name__ == '__main__':
    main()
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://www.riverbankcomputing.com/pipermail/pyqt/attachments/20121225/0f009d3a/attachment-0001.html>


More information about the PyQt mailing list