Results 1 to 3 of 3

Thread: Basic multithreading question (2 threads).

  1. #1
    Join Date
    Feb 2008
    Posts
    2
    Thanks
    1
    Qt products
    Qt4
    Platforms
    Unix/X11 Windows

    Default Basic multithreading question (2 threads).

    Hey,

    Although this is my first post, let me just start by saying I didn't surf in here to ask my question without any research on my problem first. But since my books, google, and even the ubuntu forums didn't quiet help me, i'd thought i'd come here. My code is python and most of you probably are more into C++, but since it's a Qt application, you're experience should suffice to resolve this issue :-)

    I'm pretty new to PyQt, and created my first application ImageTools this summer. It's got a rename feature that shows thumbnails, but when creating these the GUI hangs when the files get big. That's why I'd like to put the calculation of the thumbnail in a seperate secondary thread.

    Beneath is an extract of my code i've written so far:

    extract primary class:
    Qt Code:
    1. class renamewidget(QWidget):
    2. def __init__(self, leftwidget, sb, parent=None):
    3. QWidget.__init__(self, parent)
    4. ...
    5. self.lock = QMutex()
    6. self.thumbnailgenerator = thumbnailgenerator(self.lock, self)
    7.  
    8. QObject.connect(self.thumbnailgenerator, SIGNAL("finished(QPixmap)"), self.displaythumbnail)
    9.  
    10. ...
    11.  
    12. def showthumbnail(self, path):
    13. self.thumbnailgenerator.initialize(path, self.height(), self.ui.labelimagepreview)
    14. self.thumbnailgenerator.start()
    15. self.ui.labelimagepreview.setText("creating preview")
    16.  
    17. def displaythumbnail(self, pixmap):
    18. self.ui.labelimagepreview.setPixmap(scaledpixmap)
    To copy to clipboard, switch view to plain text mode 

    A bit of info:
    I create an instance of my secondary thread in the constructor (__init__) of this class, and create a QMutex. Then there are two functions, the first just sets up the secondary thread, then gives the start command, while displaying a notification in the label. The secondary thread (see below) should do the processing and emit a finished signal, which then triggers the second function. The second function should display the pixmap on the label.

    secondary class:
    Qt Code:
    1. class thumbnailgenerator(QThread):
    2. def __init__(self, lock, parent=None):
    3. super(thumbnailgenerator, self).__init__(parent)
    4. self.lock = lock
    5.  
    6. def initialize(self, path, height, label):
    7. self.path = path
    8. self.height = height
    9. self.label = label
    10.  
    11. def run(self):
    12. imagepreview = QPixmap(self.path)
    13. h = self.height / 2
    14. transfotype = Qt.FastTransformation
    15. try:
    16. self.lock.lock()
    17. scaledpixmap = imagepreview.scaledToHeight(h,transfotype)
    18. finally:
    19. self.lock.unlock()
    20.  
    21. self.emit(SIGNAL("finished(QPixmap)"), scaledpixmap)
    To copy to clipboard, switch view to plain text mode 

    When I run this, my application starts, then I select my picture, and the waiting message appears on my label. But then I get all sorts of weird output::
    Qt Code:
    1. Xlib: sequence lost (0x1ff5b > 0x3127) in reply type 0x58!
    2. Xlib: sequence lost (0x1ff53 > 0x3127) in reply type 0x52!
    3. _and so on_
    4. Xlib: sequence lost (0x1ff2c > 0x3128) in reply type 0x15!
    5. Xlib: sequence lost (0x1ff17 > 0x3128) in reply type 0x0!
    6. X Error: 21 21
    7. Major opcode: 54 (X_FreePixmap)
    8. Resource id: 0xff251f07
    9. Xlib: sequence lost (0x1ff35 > 0x3128) in reply type 0x1f!
    10. _and so on_
    11. Xlib: sequence lost (0x1ff34 > 0x3128) in reply type 0xe!
    12. Xlib: sequence lost (0x1ff0c > 0x3128) in reply type 0xf!
    13. X Error: BadAlloc (insufficient resources for operation) 11
    14. Extension: 236 (Uknown extension)
    15. Minor opcode: 177 (Unknown request)
    16. Resource id: 0xff8c8769
    17. Xlib: sequence lost (0x1ff15 > 0x3128) in reply type 0x1e!
    18. Xlib: sequence lost (0x1ff2b > 0x3128) in reply type 0xe!
    19. _and so on_
    20. Xlib: sequence lost (0x1ff05 > 0x3128) in reply type 0x2!
    21. Xlib: sequence lost (0x1ff01 > 0x3128) in reply type 0x1!
    22. imagetools.py: Fatal IO error: client killed
    To copy to clipboard, switch view to plain text mode 

    As I said, I'm pretty new to python and Qt, and have no previous expertise with threading. I'm actually not even sure if the QMutex is needed. I believe the error occurs on the statement below, since omitting the emit signal doesn't make a difference.
    Qt Code:
    1. scaledpixmap = imagepreview.scaledToHeight(h,transfotype)
    To copy to clipboard, switch view to plain text mode 

    I've googled about quiet a while now, but can't find a real sollution. I know only the primary thread can make changes to the GUI, so I tried to work my way around that with a signal. I also found some things about 'Implicit Sharing' on the Qt Docs pages, but I don't know if that's got to do anything with the problem.

    Any help or suggestions would be enormously appreciated :-)
    If this isn't the right place, please just tell me and/or refer me to the right place, I couldn't find any enthousiastic pyqt forums out there..

  2. #2
    Join Date
    Jan 2006
    Location
    Warsaw, Poland
    Posts
    5,372
    Thanks
    28
    Thanked 976 Times in 912 Posts
    Qt products
    Qt3 Qt4
    Platforms
    Unix/X11 Windows

    Default Re: Basic multithreading question (2 threads).

    The problem is that the thumbnail generator thread operates on QPixmaps and you can use these only in the GUI thread (it's because the data resides in X server). Use QImages instead.

  3. The following user says thank you to jacek for this useful post:

    jayke (21st February 2008)

  4. #3
    Join Date
    Feb 2008
    Posts
    2
    Thanks
    1
    Qt products
    Qt4
    Platforms
    Unix/X11 Windows

    Default Re: Basic multithreading question (2 threads).

    Thanks a lot for your quick reply. I've searched the Qt docs for what you've said and it seems to be right. QPixmap do rely on the underlying window structure, which can, like all GUI stuff, only be manipulated by the primary thread.

    So I've changed the QPixmap to QImage, performed the scale operation on it, and sent back the rescaled QImage to the primary thread, where I convert it to pixmap and put it on my label.

    Next problem I've encountered was that when selecting image1 then image2 while it's still calculating, the image1 thumbnail shows up, while it's supposed to be the thumb from image 2. This has to do with the thread still running, but I'll manage to work my way around that.

Similar Threads

  1. question about socket and threads?
    By oob2 in forum Qt Programming
    Replies: 2
    Last Post: 27th February 2007, 11:42
  2. Replies: 5
    Last Post: 4th August 2006, 10:12
  3. Basic question on new and delete
    By jcr in forum General Programming
    Replies: 25
    Last Post: 14th February 2006, 15:09
  4. Using QSA: A very basic question
    By yogeshm02 in forum Newbie
    Replies: 3
    Last Post: 26th January 2006, 07:34

Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  
Digia, Qt and their respective logos are trademarks of Digia Plc in Finland and/or other countries worldwide.