[QListWidget] Limites et nettoyage
Bonjour à tous
Depuis quelque temps j'étais embêté dans mes applications PyQt car elles plantaient à la fermeture. Cet évènement ne se produit que sur les applications tournant sous Windows (quoique j'ai eu quelques cas rares de memory fault sous Linux) et en plus pas tout le temps.
Je me suis attaqué récemment à ce soucis. J'avais une application utilisant des fenêtres similaires, chaque fenêtre gérant une table de bdd. Or quand j'ouvre une fenêtre X avant de quitter ça plante mais quand j'ouvre une fenêtre Y ça ne plante pas. De quoi devenir fou (chaque fenêtre faisant la même chose, avec ajout, modif, suppression dans sa table, j'avais alors calquée la seconde sur la première). Après quelques heures de tests, j'ai découvert que cela se passait avec les QListWidget lorsque le nombre d'items dépassait une certaine limite (variable en plus). Dans la fenêtre X j'avais une quinzaine de lignes et dans la Y j'en avais quelques centaines.
Pensant que cela était dû à ma façon de programmer (je progamme mes IHM à la main) j'ai rapidement développé avec designer une petite appli destinée à tester la QListWidget. Or même avec le code généré par designer+pyuic4, cela se produit aussi. Je clique sur la croix rouge, la fenêtre se ferme et windows me dit que python.exe a cessé de fonctionner.
Toutefois, si je rajoute un bouton "Quitter" et que je connecte ce bouton "quitter" à un slot dédié lequel se charge de nettoyer ma QListWidget (clear()) avant de fermer, alors plus de soucis.
Je vous mets le code de test
Code:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76
| #!/usr/bin/env python
# -*- coding: utf-8 -*-
# Form implementation generated from reading ui file 'list.ui'
#
# Created: Fri Apr 24 20:32:07 2015
# by: PyQt4 UI code generator 4.11.3
#
# WARNING! All changes made in this file will be lost!
from PyQt4 import QtCore, QtGui
import sys
try:
_fromUtf8 = QtCore.QString.fromUtf8
except AttributeError:
def _fromUtf8(s):
return s
try:
_encoding = QtGui.QApplication.UnicodeUTF8
def _translate(context, text, disambig):
return QtGui.QApplication.translate(context, text, disambig, _encoding)
except AttributeError:
def _translate(context, text, disambig):
return QtGui.QApplication.translate(context, text, disambig)
class Ui_Dialog(object):
__limit=int(sys.argv[1] if len(sys.argv) > 1 else 627) # 627 semble être la limite max
def setupUi(self, Dialog):
self.dialog=Dialog
Dialog.setObjectName(_fromUtf8("Dialog"))
Dialog.resize(480, 356)
self.verticalLayout = QtGui.QVBoxLayout(Dialog)
self.verticalLayout.setObjectName(_fromUtf8("verticalLayout"))
self.listWidget = QtGui.QListWidget(Dialog)
self.listWidget.setMaximumSize(QtCore.QSize(291, 192))
self.listWidget.setObjectName(_fromUtf8("listWidget"))
# Permet de générer n éléments de liste (n passé en paramètre)
for i in xrange(self.__limit):
item = QtGui.QListWidgetItem()
self.listWidget.addItem(item)
self.verticalLayout.addWidget(self.listWidget)
self.btn=QtGui.QPushButton(Dialog)
self.btn.setObjectName(_fromUtf8("pushButton"))
QtCore.QObject.connect(self.btn, QtCore.SIGNAL(_fromUtf8("clicked()")), self.xxx)
self.verticalLayout.addWidget(self.btn)
self.retranslateUi(Dialog)
QtCore.QMetaObject.connectSlotsByName(Dialog)
def xxx(self):
self.listWidget.clear()
self.dialog.close()
def retranslateUi(self, Dialog):
Dialog.setWindowTitle(_translate("Dialog", "Test %d items" % self.__limit, None))
__sortingEnabled = self.listWidget.isSortingEnabled()
self.listWidget.setSortingEnabled(False)
for i in xrange(self.__limit):
item=self.listWidget.item(i)
item.setText(_translate('Dialog', 'Elément %d' % (i+1), None))
self.listWidget.setSortingEnabled(__sortingEnabled)
self.btn.setText(_translate('Dialog', 'Quitter', None))
if __name__ == "__main__":
import sys
app = QtGui.QApplication(sys.argv)
Dialog = QtGui.QDialog()
ui = Ui_Dialog()
ui.setupUi(Dialog)
Dialog.show()
sys.exit(app.exec_()) |
Suffit d'enregistrer ce code dans un fichier "toto.py" et de l'appeler en lui passant le nb d'items à créer (dépassant 1000). Ensuite si on clique sur "quitter" tout va bien (la liste est nettoyée) mais si on clique sur la croix rouge alors plantage (chez-moi)
Pour info je suis sous Windows 7 avec Python 2.7.9, Qt 4.8.6, sip 4.16.7 et PyQt 4.11.3. Qt, sip et PyQt ayant été compilés depuis les sources téléchargés en utilisant MinGW.
Voilà. Si quelqu'un avait déjà rencontré le même problème, ou si inversement cela ne se passe que chez-moi ça m'intéresserait de le savoir.
Merci à tous