Я разрабатываю графический интерфейс с PyQt для визуального анализа данных, собранных во время некоторых экспериментов. Графический интерфейс просит пользователя указать каталог, в котором находятся данные для анализа:
class ExperimentAnalyzer(QtGui.QMainWindow):
## other stuff here
def loadExperiment(self):
directory = QtGui.QFileDialog.getExistingDirectory(self,
"Select Directory")
## load data from directory here
Графический интерфейс предоставляет функцию play, с помощью которой пользователь может видеть, как экспериментальные данные меняются с течением времени. Это реализовано с помощью QTimer:
def playOrPause(self):
## play
if self.appStatus.timer is None:
self.appStatus.timer = QtCore.QTimer(self)
self.appStatus.timer.connect(self.appStatus.timer,
QtCore.SIGNAL("timeout()"),
self.nextFrame)
self.appStatus.timer.start(40)
## pause
else:
self.appStatus.timer.stop()
self.appStatus.timer = None
Если я воспроизводлю временную последовательность данных, затем приостанавливаю, а затем пытаюсь изменить каталог для загрузки данных новый эксперимент, я столкнулся с ошибкой сегментации.
Используя некоторые отладочные отпечатки, я обнаружил, что приложение вылетает, когда я звоню
QtGui.QFileDialog.getExistingDirectory(self, "Select Directory")
в методе loadExperiment.
Я новичок в Qt и думаю, что неправильно обращаюсь с таймером.
Я использую PyQt 4.9, Python 2.7.3 в Ubuntu 10.04.
Изменить-1:
После ответа Люка я вернулся к своему коду.
Вот метод nextFrame, который вызывается каждый раз, когда таймер выдает тайм-аутсильный> сигнал. Он обновляет элемент QGraphicsScene, содержащийся в графическом интерфейсе:
def nextFrame(self):
image = Image.open("<some jpg>")
w, h = image.size
imageQt = ImageQt.ImageQt(image)
pixMap = QtGui.QPixmap.fromImage(imageQt)
self.scene.clear()
self.scene.addPixmap(pixMap)
self.view.fitInView(QtCore.QRectF(0, 0, w, h),
QtCore.Qt.KeepAspectRatio)
где объекты self.scene и self.view ранее были созданы в конструкторе GUI как
self.view = QtGui.QGraphicsView(self)
self.scene = QtGui.QGraphicsScene()
self.view.setScene(self.scene)
Я узнал, что комментируя эту строку:
# self.scene.addPixmap(pixMap)
и повторение той же последовательности операций, о которой сообщалось выше, ошибка сегментации больше не возникает.
Правка-2:
Запустив приложение с gdb (с python-dbg), выясняется, что ошибка сегментации возникает после вызова QPainter::drawPixmap.
(gdb) bt
#0 0xb6861f1d in ?? () from /usr/lib/i386-linux-gnu/libQtGui.so.4
#1 0xb685d491 in ?? () from /usr/lib/i386-linux-gnu/libQtGui.so.4
#2 0xb693bcd3 in ?? () from /usr/lib/i386-linux-gnu/libQtGui.so.4
#3 0xb69390bc in ?? () from /usr/lib/i386-linux-gnu/libQtGui.so.4
#4 0xb6945c77 in ?? () from /usr/lib/i386-linux-gnu/libQtGui.so.4
#5 0xb68bd424 in QPainter::drawPixmap(QPointF const&, QPixmap const&) () from /usr/lib/i386-linux-gnu/libQtGui.so.4
Следовательно, это не проблема, связанная с обработкой таймера, как я полагал в первую очередь.
Ошибка сегментации возникает из-за того, что я делаю что-то не так с pixMap.