tags:

views:

992

answers:

3

Hi, I would like to ask how to read a big file from disk and maintain the PyQt4 UI responsive (not blocked). I had moved the load of the file to a QThread subclass but my GUI thread get freezed. Any suggestions? I think it must be something with the GIL but I don't know how to sort it?

EDIT: I am using vtkGDCMImageReader from the GDCM project to read a multiframe DICOM image and display it with vtk and pyqt4. I do this load in a different thread (QThread) but my app freeze until the image is loaded. here is an example code:

class ReadThread(QThread): 
    def __init__(self, file_name): 
        super(ReadThread, self).__init__(self) 
        self.file_name = file_name 
        self.reader.vtkgdcm.vtkGDCMImageReader()

    def run(self): 
        self.reader.SetFileName(self.file_name) 
        self.reader.Update() 
        self.emit(QtCore.SIGNAL('image_loaded'), self.reader.GetOutput())
A: 

Take a look at threading-in-a-pyqt-application-use-qt-threads-or-python-threads

Martin Beckett
yes, I have been reading that article but, the fact is that when I try to read a big dicom multiframe image file with vtkGDCMImageReader from gdcm in a separate QThread or threading.Thread, my UI get blocked and THIS IS AN I/O OPERATION!!!
jmrbcu
A: 

Maybe create your reader object in the tread:

class ReadThread(QThread): 
    def __init__(self, file_name): 
        super(ReadThread, self).__init__(self) 
        self.file_name = file_name 
-       self.reader = vtkgdcm.vtkGDCMImageReader()

    def run(self): 
+       self.reader = vtkgdcm.vtkGDCMImageReader()
        self.reader.SetFileName(self.file_name) 
        self.reader.Update() 
        self.emit(QtCore.SIGNAL('image_loaded'), self.reader.GetOutput())
Gary van der Merwe
is the same thing, it block my UI
jmrbcu
+1  A: 

This link have a great step by step tutorial on using threads and signals. Unfortunately threading is not as easy as it might appear. I, at least, would hope we could build interfaces without worrying about them freezing in simpler way when I started doing this.

Anyway, I'm guessing you're directly calling the run to begin the thread. That would make the GUI freeze because you're not activating the thread.

So you'd be missing the start there, which would indirectly and properly call the run:

thread = ReadThread()
thread.begin()

class ReadThread(QThread): 
    def __init__(self, file_name): 
        super(ReadThread, self).__init__(self) 
        self.file_name = file_name 
        self.reader.vtkgdcm.vtkGDCMImageReader()

    def run(self): 
        self.reader.SetFileName(self.file_name) 
        self.reader.Update() 
        self.emit(QtCore.SIGNAL('image_loaded'), self.reader.GetOutput())

    def begin(self): 
        self.start()

But, please, do go on that link and read it through.

Cawas