Issue
Being (quite) new to both Python and Qt I'm fiddling with this code. It might be somewhat messy but I've tried to shave the code down as much as possible and still get the core-dumps.
Basically there's a button to start "something" - now it's just a for-loop - a progress bar, and a label.
Clicking the button in the interface outputs 1 to the console and then core-dumps. No data is seen in either the progress bar or the label.
I am using Python 2.7.11, Qt-4.8.7 and PySide 1.2.2.
The threaded code is from this youtube vid: https://www.youtube.com/watch?v=ivcxZSHL7jM
I've tried placing the emitting lines outside the loop, even into the MainDialog class, and it seems that as soon as the emitting signal comes from outside the MainDialog class, it crashes. It only works inside MainDialog (using static integers for testing purposes, tested after the progressbar reset).
showGui.py - nothing wrong here - (made with designer and converted with pyside):
# -*- coding: utf-8 -*-
# Form implementation generated from reading ui file 'show.ui'
#
# Created: Wed Jul 13 09:10:12 2016
# by: pyside-uic 0.2.15 running on PySide 1.2.2
#
# WARNING! All changes made in this file will be lost!
from PySide import QtCore, QtGui
class Ui_mainDialog(object):
def setupUi(self, mainDialog):
mainDialog.setObjectName("mainDialog")
mainDialog.resize(369, 171)
self.pushButton = QtGui.QPushButton(mainDialog)
self.pushButton.setGeometry(QtCore.QRect(50, 40, 84, 33))
self.pushButton.setObjectName("pushButton")
self.progressBar = QtGui.QProgressBar(mainDialog)
self.progressBar.setGeometry(QtCore.QRect(50, 110, 231, 23))
self.progressBar.setProperty("value", 0)
self.progressBar.setObjectName("progressBar")
self.label = QtGui.QLabel(mainDialog)
self.label.setGeometry(QtCore.QRect(170, 40, 81, 31))
self.label.setObjectName("label")
self.retranslateUi(mainDialog)
QtCore.QMetaObject.connectSlotsByName(mainDialog)
def retranslateUi(self, mainDialog):
mainDialog.setWindowTitle(QtGui.QApplication.translate("mainDialog", "MainWindow", None, QtGui.QApplication.UnicodeUTF8))
self.pushButton.setText(QtGui.QApplication.translate("mainDialog", "Button", None, QtGui.QApplication.UnicodeUTF8))
self.label.setText(QtGui.QApplication.translate("mainDialog", "TextLabel", None, QtGui.QApplication.UnicodeUTF8))
test.py - this fails when emitting the signals:
from __future__ import print_function
import sys
import time
from PySide import QtCore, QtGui
import showGui
from PySide.QtCore import *
from PySide.QtGui import *
class MainDialog(QDialog, showGui.Ui_mainDialog):
def __init__(self, parent=None):
super(MainDialog, self).__init__(parent)
self.setupUi(self)
self.threadclass = ThreadClass()
self.connect(self.threadclass, QtCore.SIGNAL('GFX_PROGRESS'), self.setProgress)
self.connect(self.threadclass, QtCore.SIGNAL('TEXT_PROGRESS'), self.setTextLabel)
self.connect(self.pushButton, SIGNAL("clicked()"), self.threadclass.doSomething)
self.progressBar.reset()
def setTextLabel(self, val):
self.label.setText(val)
def setProgress(self, val):
self.progressBar.setValue(val)
class ThreadClass(QtCore.QThread):
def __init__(self, parent=None):
super(ThreadClass, self).__init__(parent)
def doSomething(self):
self.runcmd()
# some more code here
def runcmd(self):
for i in range(1, 100):
print("Status at : %s " % i)
# this one crashes
self.emit(QtCore.SIGNAL('TEXT_PROGRESS'), i)
# this one crashes too
self.emit(QtCore.SIGNAL('GFX_PROGRESS'), i)
time.sleep(1)
app = QApplication(sys.argv)
form = MainDialog()
form.show()
app.exec_()
Solution
Do not use the old-style signal and slot syntax. It's bug-prone, and does not raise an exception if you get it wrong. In addition to that, it looks like the implementation is somewhat broken in PySide. I converted your code example to PyQt4, and it does not dump core.
To get your example working in PySide, you first need to switch to the new-style signal and slot syntax. Also, your current threading implementation is wrong. It doesn't actually start the worker thread, so the all the code will run in the main thread, and it will block the gui.
The following fixes should get the example working as expected:
class MainDialog(QDialog, Ui_mainDialog):
def __init__(self, parent=None):
..
# use new-style connections
self.threadclass.gfxProgress.connect(self.setProgress)
self.threadclass.textProgress.connect(self.setTextLabel)
self.pushButton.clicked.connect(self.threadclass.doSomething)
class ThreadClass(QtCore.QThread):
# define new-style signals
gfxProgress = QtCore.Signal(int)
textProgress = QtCore.Signal(str)
def __init__(self, parent=None):
super(ThreadClass, self).__init__(parent)
def doSomething(self):
# start the thread
# by default, this will automatically call run()
self.start()
def run(self):
for i in range(1, 100):
print("Status at : %s " % i)
# emit the new-style signals
self.gfxProgress.emit(i)
self.textProgress.emit(str(i))
time.sleep(1)
Answered By - ekhumoro
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.