For example:
#!/usr/bin/env python3
import sys
from PySide import QtCore, QtGui
class Dialog(QtGui.QDialog):
def __init__(self):
QtGui.QDialog.__init__(self)
button = QtGui.QPushButton("test")
layout = QtGui.QVBoxLayout()
layout.addWidget(button)
self.setLayout(layout)
app = QtGui.QApplication(sys.argv)
toast = Dialog()
toast.show()
app.exec_()
print("App freezes the main process!")
The last print() function will not be executed until you close the dialog.
I am working on a script that only uses qt for displaying some content that does not require user interaction, so I would prefer the gui code runs in background.
This is not possible. Qt documentation states:
Although QObject is reentrant, the GUI classes, notably QWidget and all its subclasses, are not reentrant. They can only be used from the main thread. As noted earlier, QCoreApplication::exec() must also be called from that thread.
(emphasis mine)
This answer suggests on the other hand that in reality this is not true :) However it seems that PySide sticks to the official version:
This can be verified by the following code sample:
import sys
import threading
from PySide import QtCore, QtGui
class Dialog(QtGui.QDialog):
def __init__(self):
QtGui.QDialog.__init__(self)
button = QtGui.QPushButton("test")
layout = QtGui.QVBoxLayout()
layout.addWidget(button)
self.setLayout(layout)
app = QtGui.QApplication(sys.argv)
toast = Dialog()
toast.show()
t = threading.Thread(target = lambda: app.exec_())
t.daemon = True
t.start()
print("App freezes the main process!")
input()
which produces the following output:
App freezes the main process!
QApplication::exec: Must be called from the main thread
(and a crash, on my machine). I have also verified the option with creating the app within the other thread - it works, but crashes on exit.
So the solution seems to let Qt have the main thread, and organize your processing in a separate thread. This shouldn't really be a problem: if you'll separate your concerns well it won't make a difference for your console-app part on which thread it's running.
I'm not sure if the PySide imposes any restrictions, but here's how it's done in C++:
Instantiate QApplication in a secondary thread.
Create your dialog in that same thread.
Call either QDialog::exec() OR {QApplication::exec() plus QDialog::show()} in that same thread.
Make sure that your secondary thread has fully shut down before you quit your app.
Yes, the Qt documentation currently says that only the main thread is allowed. However, there is nothing in the Qt source code that forbids creating QApplication in a secondary thread and then using GUI classes in that thread (for Windows and Linux). The documentation should be changed.
Mac OS X is different though -- the Cocoa framework only allows GUI operations in the main thread.
Related
I have created a relatively complex PyQt program and am trying to implement threads so that when the program encounters a part of the program which is particularly CPU intensive, the GUI will remain refreshed and responsive throughout. Sadly though, I am having some difficulties with the threading.
I am using Python 2.7 for reasons that I don't believe to be relevant.
Anyway, the entire program runs within one class and calls upon a PyQt designer .ui file in order to display the actual GUI. When a particular button is pressed, in order to shred a file, it calls a function within that class that then starts a thread using the 'thread' module, yes, outdated, I know. The shredding function that is then called from this commences the shredding of the file. Throughout the shredding of the file, the actual shredding function interacts and adds bits to the GUI in order to keep the user up to date on what is happening.
During the execution of the function the GUI continues to be refreshed, however it does become a little laggy, I can cope with that. However, when that function is complete, instead of smoothly continuing and allowing the user to keep using the program, the program throws a complete hissy fit and simply just stops working and has to be closed.
Hopefully someone can assist me here. I would greatly appreciate as much detail as possible as I have been searching around for a way to cope with this for a good number of weeks now.
I am using PyQt4.
Here's a simple demo of threading in pyqt5. Qt has it's own threading class that works pretty well.
from PyQt5 import QtCore, QtGui, QtWidgets
from PyQt5.QtCore import pyqtSignal
import sys
import time
class TheBoss(QtWidgets.QWidget):
def __init__(self, parent=None):
super(TheBoss, self).__init__(parent)
self.resize(300,200)
self.VL = QtWidgets.QVBoxLayout(self)
self.label = QtWidgets.QLabel()
self.VL.addWidget(self.label)
self.logger = Logger()
self.logger.sec_signal.connect(self.label.setText)
self.logger.start()
def closeEvent(self,event):
self.logger.terminate()
class Logger(QtCore.QThread):
sec_signal = pyqtSignal(str)
def __init__(self, parent=None):
super(Logger, self).__init__(parent)
self.current_time = 0
self.go = True
def run(self):
#this is a special fxn that's called with the start() fxn
while self.go:
time.sleep(1)
self.sec_signal.emit(str(self.current_time))
self.current_time += 1
if __name__ == '__main__':
app = QtWidgets.QApplication(sys.argv)
app.setApplicationName("Thread Example")
window = TheBoss()
window.show()
sys.exit(app.exec_())
Hello StackExchange community,
first off, you have all been a great help for me, thanks so much. First time question:
I am currently writing a PyQt GUI application and I see that it crashes on windows systems, also it gives me a segfault on my machine at home while it works on the one at work (both linux mint 17). After some research, I realize that I have probably created a thread-unsafe GUI because I have several objects that call each others methods.
From another stackoverflow question: GUI widgets may be accessed only from main thread, meaning the thread that calls QApplication.exec(). Access to GUI widgets from any other thread – what you're doing with your calls to self.parent() – is undefined behaviour, in your case this means crashes.
From Qt docs: Although QObject is reentrant, the GUI classes, notably QWidget and all its subclasses, are not reentrant. They can only be used from the main thread. As noted earlier, QCoreApplication::exec() must also be called from that thread.
So in the end, I figure that I should only use the signal-slot system for doing so.
Is this correct?
Is this only needed for function calls, or can I manipulate the fields of some objects from other objects at runtime in a thread safe manner? for example, I have a options object that is accessed from multiple other objects, and I frequently change parameters there from different sources. Thread safe or unsafe?
The next thing, is that I have a problem recreating this thread-unsafe behaviour in example code. Qt documentation says that QObjects live in different threads. This means, the following Qt application should be thread unsafe (if I got it correctly).
from PyQt4 import QtGui
import sys
class TestWidget(QtGui.QWidget):
def __init__(self,string):
super(TestWidget,self).__init__()
self.button = QtGui.QPushButton(string,parent=self)
self.button.clicked.connect(self.buttonClicked)
# just to check, and yes, lives in it's own thread
print self.thread()
def buttonClicked(self):
# the seemingly problematic line
self.parent().parent().statusBar().showMessage(self.button.text())
pass
pass
class MainWindow(QtGui.QMainWindow):
def __init__(self):
super(MainWindow,self).__init__()
Layout = QtGui.QHBoxLayout()
for string in ['foo','bar']:
Layout.addWidget(TestWidget(string))
CentralWidget = QtGui.QWidget(self)
CentralWidget.setLayout(Layout)
self.setCentralWidget(CentralWidget)
self.statusBar()
self.show()
pass
pass
if __name__ == '__main__':
app = QtGui.QApplication(sys.argv)
M = MainWindow()
sys.exit(app.exec_())
but it runs on my mine as well on windows machines fine.
Why? Is this actually thread-unsafe and could crash, but it just doesn't?
Thanks for helping me to sort this out ...
Is this correct?
Yes, you should only use the signal-slot system for interactions ammong q-objects.
This is how it's meant to be.
Is this only needed for function calls, or can I manipulate the fields of some objects
from other objects at runtime in a thread safe manner?
I have a options object that is accessed from multiple other objects...
If by objects here you meant Q-objects:
Your options object should have support for the signal-slot mechanism, you can achieve this
deriving options from QObject.
class Options(QtCore.QObject):
optionUpdated = QtCore.pyqtSignal(object)
def __init__(self):
self.__options = {
'option_1': None
}
def get_option(self, option):
return self.__options.get(option)
def set_option(self, option, value):
self.__options[option] = value
self.optionUpdated.emit(self)
and then all widgets/objects using this options should have a slot that connect to this singal.
A simple example:
options = Options()
some_widget = SomeWidget()
options.optionUpdated.connect(some_widget.options_updated) // Is like you implement the observer pattern, right?
Why? Is this actually thread-unsafe and could crash, but it just doesn't?
thread-unsafe doesn't mean "the crash is guaranteed" but "this might crash" or "there is a high probability for this to crash".
From pyqt API doc QObject.thread :
Returns the thread in which the object lives.
Erratum
As pointed by ekumoro, I've re-checked my previous position about each object leaving in a different thread, and ... I was wrong!
QObject.thread will return a different QThread instance for each object but QThread is not actually a thread is just a wrapper for those threads provided by the OS.
So the code don't really have the problem af several object sliving in different threads.
I have modified the code you have used for demostration a little bit for simplicity:
from PyQt4 import QtGui
import sys
class TestWidget(QtGui.QWidget):
def __init__(self,string):
super(TestWidget,self).__init__()
# just to check, and yes, lives in it's own thread
print("TestWidget thread: {}".format(self.thread()))
class MainWindow(QtGui.QMainWindow):
def __init__(self):
super(MainWindow,self).__init__()
print("Window thread: {}".format(self.thread()))
Layout = QtGui.QHBoxLayout()
for string in ['foo','bar']:
Layout.addWidget(TestWidget(string))
self.show()
if __name__ == '__main__':
app = QtGui.QApplication(sys.argv)
M = MainWindow()
sys.exit(app.exec_())
and yes, this prints:
Window thread: <PyQt4.QtCore.QThread object at 0x00000000025C1048>
TestWidget thread: <PyQt4.QtCore.QThread object at 0x00000000025C4168>
TestWidget thread: <PyQt4.QtCore.QThread object at 0x00000000025C41F8>
demostrating each control lives in its own thread.
Now, you have the signal-slot mechanism to deal with this "thread-safely", any other approach will not be thread-safe.
Answers to your questions:
GUI widgets can only be accessed from the main thread (the one that runs
QApplication.exec_()). Signals and slots are thread safe by default since
Qt 4
Any call leading to direct Qt graphics objects manipulation from another thread than the main one is not thread-safe => will crash
There is no threads involved in the code of your question (where are the threads???),
it's not true that different QObjects live in different threads. Maybe the crash you have has nothing to do
with threads ?
As a follow-up to some of the comments, below is an test script that shows how to check which thread the code is executing in:
from PyQt4 import QtCore, QtGui
class Worker(QtCore.QObject):
threadInfo = QtCore.pyqtSignal(object, object)
#QtCore.pyqtSlot()
def emitInfo(self):
self.threadInfo.emit(self.objectName(), QtCore.QThread.currentThreadId())
class Window(QtGui.QWidget):
def __init__(self):
super(Window, self).__init__()
self.button = QtGui.QPushButton('Test', self)
layout = QtGui.QVBoxLayout(self)
layout.addWidget(self.button)
self.thread = QtCore.QThread(self)
self.worker1 = Worker()
self.worker1.setObjectName('Worker1')
self.worker1.moveToThread(self.thread)
self.worker1.threadInfo.connect(self.handleShowThreads)
self.button.clicked.connect(self.worker1.emitInfo)
self.worker2 = Worker()
self.worker2.setObjectName('Worker2')
self.worker2.threadInfo.connect(self.handleShowThreads)
self.button.clicked.connect(self.worker2.emitInfo)
self.thread.start()
def handleShowThreads(self, name, identifier):
print('Main: %s' % QtCore.QThread.currentThreadId())
print('%s: %s\n' % (name, identifier))
def closeEvent(self, event):
self.thread.quit()
self.thread.wait()
if __name__ == '__main__':
import sys
app = QtGui.QApplication(sys.argv)
window = Window()
window.show()
sys.exit(app.exec_())
I know this has been asked many times before. I read all of those threads, and my case seems different. Everybody else who has this trouble has a few straightforward causes that I think I’ve ruled out, such as:
Starting a timer with no event loop running
Starting/stopping a timer from a thread other than the one that created the timer
Failing to set the parent property of a widget, leading to problems with the order of destruction
Below I have a minimal code sample that demonstrates the problem. Notice that I’ve started no threads or timers. I also have set the parent of every widget. If I remove the graph widgets, the problem goes away, so one is tempted to blame pyQtGraph, however, if I include the plot widgets but exclude all the blank tabs (i.e. every tab except tabCatchaTiger), the problem also goes away, and that seems to vindicate pyQtGraph.
Versions:
Windows 7
Python 2.7.8
Wing IDE 5.0.9-1
PyQt 4.11.1
PyQwt 5.2.1
PyQtGraph 0.9.8
Test case:
from PyQt4 import Qt, QtGui, QtCore
import PyQt4.Qwt5 as Qwt
import pyqtgraph as pg
pg.functions.USE_WEAVE = False # Lets pyqtgraph plot without gcc
pg.setConfigOption('background', 'w')
pg.setConfigOption('foreground', 'k')
# GUI for visualizing data from database
class crashyGUI(QtGui.QWidget) :
def __init__(self) :
# Make the window
QtGui.QWidget.__init__(self)
self.resize(700, QtGui.QDesktopWidget().screenGeometry(self).height()*.85)
self.setWindowTitle('Data Visualization')
# Create tab interface
tabWidget = QtGui.QTabWidget(self)
# define the tab objects
self.tabEeny = QtGui.QWidget(tabWidget)
self.tabMeeny = QtGui.QWidget(tabWidget)
self.tabMiney = QtGui.QWidget(tabWidget)
self.tabMoe = QtGui.QWidget(tabWidget)
self.tabCatchaTiger = QtGui.QWidget(tabWidget)
self.tabByThe = QtGui.QWidget(tabWidget)
self.tabToe = QtGui.QWidget(tabWidget)
# Initialize the tab objects
self.initTabCatchaTiger()
###########################################
############### Main Layout ###############
###########################################
tabWidget.addTab(self.tabEeny, 'Eeny')
tabWidget.addTab(self.tabMeeny, 'Meeny')
tabWidget.addTab(self.tabMiney, 'Miney')
tabWidget.addTab(self.tabMoe, 'Moe')
tabWidget.addTab(self.tabCatchaTiger, 'Catch a Tiger')
tabWidget.addTab(self.tabByThe, 'By The')
tabWidget.addTab(self.tabToe, 'Toe')
self.mainLayout = QtGui.QVBoxLayout(self)
self.mainLayout.addWidget(tabWidget)
self.setLayout(self.mainLayout)
def initTabCatchaTiger(self):
###########################################
############# ADC Capture Tab #############
###########################################
# define tab layout
grid = QtGui.QGridLayout(self.tabCatchaTiger)
# create copy of adc plot and add to row 3 of the grid
self.catchaTigerPlot1 = pg.PlotWidget(name = 'Catch a Tiger 1', parent = self.tabCatchaTiger)
self.catchaTigerPlot1.setTitle('Catch a Tiger 1')
grid.addWidget(self.catchaTigerPlot1, 2, 0, 1, 8)
self.catchaTigerPlot2 = pg.PlotWidget(name = 'Catch a Tiger 2', parent = self.tabCatchaTiger)
self.catchaTigerPlot2.setTitle('Catch a Tiger 2')
grid.addWidget(self.catchaTigerPlot2, 3, 0, 1, 8)
# set layout for tab
self.tabCatchaTiger.setLayout(grid)
def closeEvent(self, event) :
pass
def main() :
# open a QApplication and dialog() GUI
app = QtGui.QApplication([])
windowCrashy = crashyGUI()
windowCrashy.show()
app.exec_()
main()
There seem to be two closely-related issues in the example.
The first one causes Qt to print the QObject::startTimer: QTimer can only be used with threads started with QThread messages on exit.
The second one (which may not affect all users) causes Qt to print QPixmap: Must construct a QApplication before a QPaintDevice, and then dump core on exit.
Both of these issues are caused by python deleting objects in an unpredicable order when it exits.
In the example, the second issue can be fixed by adding the following line to the __init__ of the top-level window:
self.setAttribute(QtCore.Qt.WA_DeleteOnClose)
Unless QApplication.setQuitOnLastWindowClosed has been changed to False, this will ensure that the application quits at the right time, and that Qt has a chance to automatically delete all the children of the top-level window before the python garbage-collector gets to work.
However, for this to be completely successful, all the relevant objects must be linked together in a parent-child hierarchy. The example code does this where it can, but there seem to be some critical places in the initialization of the PlotWidget class where it is not done.
In particular, there is nothing to ensure that the central item of the PlotWidget has a parent set when it is created. If the relevant part of the code is changed to this:
class PlotWidget(GraphicsView):
...
def __init__(self, parent=None, background='default', **kargs):
GraphicsView.__init__(self, parent, background=background)
...
self.plotItem = PlotItem(**kargs)
# make sure the item gets a parent
self.plotItem.setParent(self)
self.setCentralItem(self.plotItem)
then the first issue with the QTimer messages also goes away.
Here's a better answer:
You are allowing the QApplication to be collected before python exits. This causes two different issues:
The QTimer error messages are caused by pyqtgraph trying to track its ViewBoxes after the QApplication has been destroyed.
The crash appears to be intrinsic to Qt / PyQt. The following crashes in the same way:
from PyQt4 import Qt, QtGui, QtCore
def main() :
app = QtGui.QApplication([])
x = QtGui.QGraphicsView()
s = QtGui.QGraphicsScene()
x.setScene(s)
x.show()
app.exec_()
main()
You can fix it by adding global app to your main function, or by creating the QApplication at the module level.
Try to write this in block of __init__:
self.setAttribute(Qt.WA_DeleteOnClose)
Personally, I don't put any effort into chasing exit crashes anymore--just use pg.exit() and be done with it.
(but if you do happen to find a bug in pyqtgraph, don't hesitate to open an issue on github)
I had this happen as well and in my case it was caused by a call to deleteLater() on the aboutToQuit-Signal of the application, like so:
def closeEvent(self, *args, **kwargs):
self.deleteLater()
if __name__ == "__main__":
application = QtWidgets.QApplication(sys.argv)
window = testApplication()
# Handle application exit
application.aboutToQuit.connect(window.closeEvent)
# System exit
sys.exit(application.exec_())
Getting rid of the deleteLater on the whole window seemed to solve it.
I have written a Qt application in c++ which embeds the Python interpreter and makes use of PyQt to allow for scriptable user interfaces for data analysis. The Python code does some computations on the data and returns a QWidget (containing various plots etc.) which gets inserted into the main application.
I would like to spawn a new QThread from Python to allow control to return to the c++ application so that heavy computations do not block the main thread in which the GUI runs. The problem is that as soon as control is returned back to the c++ application, the thread appears to go to sleep until the Python interpreter is somehow invoked again, eg. a mouseover event on a matplotlib plot. I suspect this is somehow due to Python's GIL.
How can I have a QThread created from Python continue to run after control passes back to the embedding application?
I am using the following code to test. The embedding application calls test_thread() and adds the returned container to a QTabwidget. The thread only executes as I generate mouse events over the matplotlib plot.
import time
from PyQt4 import QtCore, QtGui
from PyQt4.QtCore import pyqtSignal, pyqtSlot
from matplotlib.figure import Figure
from matplotlib.backends.backend_qt4agg import FigureCanvasQTAgg as FigureCanvas
app = QtGui.QApplication.instance()
class Worker(QtCore.QObject):
finished = pyqtSignal()
def __init__(self):
QtCore.QObject.__init__(self)
def do_work(self):
for i in range(0, 10):
print 'worker running'
time.sleep(1)
self.finished.emit()
class Controller(QtCore.QObject):
def __init__(self):
QtCore.QObject.__init__(self)
self.thread = QtCore.QThread()
self.worker = Worker()
self.worker.moveToThread(self.thread)
self.worker.finished.connect(self.thread.quit)
self.thread.started.connect(self.worker.do_work)
self.thread.finished.connect(app.exit)
def start_thread(self):
self.thread.start()
class Container(QtGui.QWidget):
def __init__(self):
QtGui.QWidget.__init__(self)
self.controller = Controller()
self.controller.start_thread()
self.fig = Figure(dpi=72, facecolor=(1, 1, 1), edgecolor=(0, 0, 0))
self.fig.add_subplot(111)
self.canvas = FigureCanvas(self.fig)
self.layout = QtGui.QVBoxLayout()
self.layout.addWidget(self.canvas)
self.setLayout(self.layout)
def test_thread():
container = Container()
return container
CPython is single threaded because of GIL or Global Interpreter Lock. You cannot run more than 1 concurrent thread from python.
https://wiki.python.org/moin/GlobalInterpreterLock
Qt is not blocking you here, python is. The only workaround here is to spawn separate python process for your worker "thread" then use IPC (sockets, shared memory, etc) to communicate between processes. Qt provides interfaces for these IPC mechanisms. You will just have to serialize your interprocess communication.
http://qt-project.org/doc/qt-5/QSharedMemory.html
http://qt-project.org/doc/qt-5/QLocalSocket.html
This assumed you were asking about concurrency. Regarding something else, and editing answer to clarify jurisdiction,
How can I have a QThread created from Python continue to run after control passes back to the embedding application?
This is 100% up to the embedding application. The python interpreter must be allowed to continue to run by the embedding application. If the embedding application does not allow python to continue to run, then any attempts to circumvent this will result in problems.
This may be a little long post, so, thanks in advance to be with me till the end. Here is the problem, (i think a fairly basic one, just my inexperience with PiSide and Qt making it harder for me.) I have a main window with one menu item, suppose "Process". the code is following -
from PySide import QtCore, QtGui
class Ui_MainWindow(object):
def setupUi(self, MainWindow, AppObj):
.
.
self.statusbar = QtGui.QStatusBar(MainWindow)
self.statusbar.setObjectName("statusbar")
MainWindow.setStatusBar(self.statusbar)
.
.
.
self.actionProcess = QtGui.QAction(MainWindow)
self.actionProcess.setObjectName("actionProcess")
self.actionProcess.triggered.connect(self.myappObj.menuActionProcess)
.
Here self.myappobj refers to a app class I have created which acts as the main logic controller for my app. The code -
from PySide import QtCore, QtGui
from MainWindow import Ui_MainWindow
class App(QtGui.QDialog):
def __init__(self, parent=None):
self.__mainWindow = QtGui.QMainWindow()
self.__mainWindowDesignContext = Ui_MainWindow()
self.__mainWindowDesignContext.setupUi(self.__mainWindow, self)
self.__mainWindow.show()
def menuActionProcess(self):
self.processThread = BatchProcesser()
self.progressBar = QtGui.QProgressBar()
statusBar.addWidget(self.progressBar)
self.progressBar.show()
self.progressBar.setMinimum(0)
self.progressBar.setMaximum(100)
QtCore.QObject.connect(self.processThread, QtCore.SIGNAL("progress(int)"),self.progressBar, QtCore.SLOT("setValue(int)"), QtCore.Qt.DirectConnection)
if not self.processThread.isRunning():
self.processThread.exiting = False
self.processThread.start()
So, it is easy to see that what i am trying to do here is to create a main window. Add a menu there called "Process", clicking on which should trigger the callback menuActionProcess method in the app class, where I am making a progress bar and attaching it with the Status Bar of my main window (The actual code has many other things, what i give here is the necessary parts rearranged as an pseudo example)
and finally in the BatchProcesser class mentioned in the above code, I am doing this -
from PySide.QtGui import *
from PySide.QtCore import *
class BatchProcesser(QThread):
__errorHappened = False
def __init__(self, parent=None):
QThread.__init__(self, parent)
self.exiting = False
def run(self):
for a in range(101):
print a
QThread.msleep(100)
self.emit(SIGNAL("progress(int)"), a)
print a
In my understanding this should update the Progress Bar attached to the Status Bar in a different thread than the main thread. This will allow the user to interact with the GUI freely.
Right now, If i try to rin this, everything is fine until i hit the Process menu. Then, the progress bar appeases but does not update and the console is full with error -
0 QPixmap: It is not safe to use pixmaps outside the GUI thread
QPixmap: It is not safe to use pixmaps outside the GUI thread
QPixmap: It is not safe to use pixmaps outside the GUI thread
QPixmap: It is not safe to use pixmaps outside the GUI thread
0
1
QPixmap: It is not safe to use pixmaps outside the GUI thread
QPixmap: It is not safe to use pixmaps outside the GUI thread
QPixmap: It is not safe to use pixmaps outside the GUI thread
QPixmap: It is not safe to use pixmaps outside the GUI thread
[xcb] Unknown request in queue while dequeuing
[xcb] Most likely this is a multi-threaded client and XInitThreads has
not been called
[xcb] Aborting, sorry about that.
python: ../../src/xcb_io.c:178: dequeue_pending_request: Assertion
`!xcb_xlib_unknown_req_in_deq' failed.
Aborted (core dumped)
Any help is very much required for me. I am unable to find out and/ot point the original reason of the error and fix the same.
The problem lies in how you connect the signal to the slot:
QtCore.QObject.connect(self.processThread, QtCore.SIGNAL("progress(int)"),self.progressBar, QtCore.SLOT("setValue(int)"), QtCore.Qt.DirectConnection)
Here, you explicitely enforce a DirectConnection. This is wrong! It makes the slot be processed in the caller's thread. This means that the GUI update of the progressBar happens in the process thread, not in the GUI thread. However, drawing is only allowed in the GUI thread.
It is perfectly fine to connect a signal from one thread to a slot from another. However, you need either AutoConnection (the default, which will recognize the threads and use QueuedConnection) or QueuedConnection.
This line should fix your problem:
QtCore.QObject.connect(self.processThread, QtCore.SIGNAL("progress(int)"),self.progressBar, QtCore.SLOT("setValue(int)"), QtCore.Qt.QueuedConnection)
See http://doc.qt.io/archives/qt-4.7/qt.html#ConnectionType-enum.