[PyQt] QThread and qRegisterMetaType

2010-10-17 Thread Janwillem van Dijk
I want the output of a function that runs in a thread to be shown in a 
QPlainTextEdit on the main window. Now this crashes with a message that 
I sould use qRegisterMetaType. There are dozens of entries on the web on 
this but I could not find any that tells how to. At least not how to in 
python.


My handicap is that I have not too much experience with oo-programming 
and none at all with c++. Thus suggestions like call 
qRegisterMetaType() to register the data type before you establish the 
connection. are of no help and I have no idea what to make of things 
like qRegisterMetaTypeVolumeType( VolumeType );


Please can someone tell me what to do with the small example below to 
get it working.


#!/usr/bin/python

Small test application for threaded output to a QPlainTextEdit.
The main window consists of three buttons and the QPlainTextEdit
- pressButtonInsert clicked is connected to slotInsert: append text to 
the edit widget

- pressButtonThread clicked is connected to slotInsertThreaded:
append text to edit widget from within a separate thread
- pressButtonClear clicked is connected to slotClear: clear the edit widget

import sys, time
from PyQt4 import QtCore, QtGui
from qPlainTextEditGui import Ui_Form #the main form containing the 4 
widgets

class MyForm(QtGui.QMainWindow):
def __init__(self, parent=None):
QtGui.QWidget.__init__(self, parent)
self.ui = Ui_Form()
self.ui.setupUi(self)
def slotClear(self):
print('ButtonClear triggered')
self.ui.plainTextEdit.clear()
def slotInsert(self):
print('ButtonInsert triggered')
append_to_edit(self.ui.plainTextEdit)
def slotInsertThreaded(self):
print('ButtonTreaded triggered')
self.work = work_thread(self.ui.plainTextEdit)
self.work.start()

class work_thread(QtCore.QThread):

After http://joplaete.wordpress.com/2010/07/21/threading-with-pyqt4/

def __init__(self, edit, parent=None):
QtCore.QThread.__init__(self, parent)
self.edit = edit
def run(self):
append_to_edit(self.edit)

def append_to_edit(edit):
for i in range(5):
edit.appendPlainText('line %d' % i)
time.sleep(0.5)

if __name__ == __main__:
app = QtGui.QApplication(sys.argv)
myapp = MyForm()
myapp.show()
sys.exit(app.exec_())

Now it works fine when pressButtonInsert is triggered but returns this 
when pressButtonThread is triggered:

QObject::connect: Cannot queue arguments of type 'QTextBlock'
(Make sure 'QTextBlock' is registered using qRegisterMetaType().)
QObject::connect: Cannot queue arguments of type 'QTextCursor'
(Make sure 'QTextCursor' is registered using qRegisterMetaType().)

Many thanks for helping me out,
Janwillem
___
PyQt mailing listPyQt@riverbankcomputing.com
http://www.riverbankcomputing.com/mailman/listinfo/pyqt


Re: [PyQt] QThread and qRegisterMetaType

2010-10-17 Thread Hans-Peter Jansen
On Sunday 17 October 2010, 19:04:16 Janwillem van Dijk wrote:
 I want the output of a function that runs in a thread to be shown in
 a QPlainTextEdit on the main window. Now this crashes with a message
 that I sould use qRegisterMetaType. There are dozens of entries on
 the web on this but I could not find any that tells how to. At least
 not how to in python.

 My handicap is that I have not too much experience with
 oo-programming and none at all with c++. Thus suggestions like call
 qRegisterMetaType() to register the data type before you establish
 the connection. are of no help and I have no idea what to make of
 things like qRegisterMetaTypeVolumeType( VolumeType );

This isn't possible is PyQt anyway, but these are signs of you doing 
something fundamentally wrong here.

 Please can someone tell me what to do with the small example below to
 get it working.

Please read the text: Reentrancy and Thread-Safety in Qt's 
documentation and use the back and forth links to explore this topic to 
some extend. 98% of what is said there is applicable to PyQt, too.

The example, that your code refers to did it right by using signals and 
slots to communicate between the main thread and the worker thread. You 
are not allowed to access widgets directly. 

BTW, your example isn't runnable since your ui file is missing.

 #!/usr/bin/python
 
 Small test application for threaded output to a QPlainTextEdit.
 The main window consists of three buttons and the QPlainTextEdit
 - pressButtonInsert clicked is connected to slotInsert: append text
 to the edit widget
 - pressButtonThread clicked is connected to slotInsertThreaded:
  append text to edit widget from within a separate thread
 - pressButtonClear clicked is connected to slotClear: clear the edit
 widget 
 import sys, time
 from PyQt4 import QtCore, QtGui
 from qPlainTextEditGui import Ui_Form #the main form containing the 4
 widgets
 class MyForm(QtGui.QMainWindow):
  def __init__(self, parent=None):
  QtGui.QWidget.__init__(self, parent)
  self.ui = Ui_Form()
  self.ui.setupUi(self)
  def slotClear(self):
  print('ButtonClear triggered')
  self.ui.plainTextEdit.clear()
  def slotInsert(self):
  print('ButtonInsert triggered')
  append_to_edit(self.ui.plainTextEdit)
  def slotInsertThreaded(self):
  print('ButtonTreaded triggered')
  self.work = work_thread(self.ui.plainTextEdit)
   ^
   Bad idea starts here

  self.work.start()

 class work_thread(QtCore.QThread):
  
  After
 http://joplaete.wordpress.com/2010/07/21/threading-with-pyqt4/ 
  def __init__(self, edit, parent=None):
  QtCore.QThread.__init__(self, parent)
  self.edit = edit
  def run(self):
  append_to_edit(self.edit)

 def append_to_edit(edit):
  for i in range(5):
  edit.appendPlainText('line %d' % i)
   ^^^
   *Bang*

  time.sleep(0.5)
   
   bad style, better use QThread.msleep()


 if __name__ == __main__:
  app = QtGui.QApplication(sys.argv)
  myapp = MyForm()
  myapp.show()
  sys.exit(app.exec_())

 Now it works fine when pressButtonInsert is triggered but returns
 this when pressButtonThread is triggered:
 QObject::connect: Cannot queue arguments of type 'QTextBlock'
 (Make sure 'QTextBlock' is registered using qRegisterMetaType().)
 QObject::connect: Cannot queue arguments of type 'QTextCursor'
 (Make sure 'QTextCursor' is registered using qRegisterMetaType().)

 Many thanks for helping me out,
 Janwillem

Good luck,
Pete
___
PyQt mailing listPyQt@riverbankcomputing.com
http://www.riverbankcomputing.com/mailman/listinfo/pyqt