i read this article How To Really, Truly Use QThreads; The Full Explanation, it says instead of subclass qthread, and reimplement run(), one should use moveToThread to push a QObject onto QThread instance using moveToThread(QThread*)
here is the c++ example, but i don't know how to convert it to python code.
class Worker : public QObject
 {
     Q_OBJECT
     QThread workerThread;
 public slots:
     void doWork(const QString ¶meter) {
         // ...
         emit resultReady(result);
     }
 signals:
     void resultReady(const QString &result);
 };
 class Controller : public QObject
 {
     Q_OBJECT
     QThread workerThread;
 public:
     Controller() {
         Worker *worker = new Worker;
         worker->moveToThread(&workerThread);
         connect(workerThread, SIGNAL(finished()), worker, SLOT(deleteLater()));
         connect(this, SIGNAL(operate(QString)), worker, SLOT(doWork(QString)));
         connect(worker, SIGNAL(resultReady(QString)), this, SLOT(handleResults(QString)));
         workerThread.start();
     }
     ~Controller() {
         workerThread.quit();
         workerThread.wait();
     }
 public slots:
     void handleResults(const QString &);
 signals:
     void operate(const QString &);
 };
QThread* thread = new QThread;
Worker* worker = new Worker();
worker->moveToThread(thread);
connect(worker, SIGNAL(error(QString)), this, SLOT(errorString(QString)));
connect(thread, SIGNAL(started()), worker, SLOT(process()));
connect(worker, SIGNAL(finished()), thread, SLOT(quit()));
connect(worker, SIGNAL(finished()), worker, SLOT(deleteLater()));
connect(thread, SIGNAL(finished()), thread, SLOT(deleteLater()));
thread->start();
i've been using this method to generate a qthread , but as you can see, it's using the not recommended way. how can i re-write it to use the preferred method ?
class GenericThread(QThread):
    def __init__(self, function, *args, **kwargs):
        QThread.__init__(self)
        # super(GenericThread, self).__init__()
        self.function = function
        self.args = args
        self.kwargs = kwargs
    def __del__(self):
        self.wait()
    def run(self, *args):
        self.function(*self.args, **self.kwargs)
edit: two years later ... I tried qris' code, it works and in different thread
import sys
import time
from PyQt4 import QtCore, QtGui
from PyQt4.QtCore import pyqtSignal, pyqtSlot
import threading
def logthread(caller):
    print('%-25s: %s, %s,' % (caller, threading.current_thread().name,
                              threading.current_thread().ident))
class MyApp(QtGui.QWidget):
    def __init__(self, parent=None):
        QtGui.QWidget.__init__(self, parent)
        self.setGeometry(300, 300, 280, 600)
        self.setWindowTitle('using threads')
        self.layout = QtGui.QVBoxLayout(self)
        self.testButton = QtGui.QPushButton("QThread")
        self.testButton.released.connect(self.test)
        self.listwidget = QtGui.QListWidget(self)
        self.layout.addWidget(self.testButton)
        self.layout.addWidget(self.listwidget)
        self.threadPool = []
        logthread('mainwin.__init__')
    def add(self, text):
        """ Add item to list widget """
        logthread('mainwin.add')
        self.listwidget.addItem(text)
        self.listwidget.sortItems()
    def addBatch(self, text="test", iters=6, delay=0.3):
        """ Add several items to list widget """
        logthread('mainwin.addBatch')
        for i in range(iters):
            time.sleep(delay)  # artificial time delay
            self.add(text+" "+str(i))
    def test(self):
        my_thread = QtCore.QThread()
        my_thread.start()
        # This causes my_worker.run() to eventually execute in my_thread:
        my_worker = GenericWorker(self.addBatch)
        my_worker.moveToThread(my_thread)
        my_worker.start.emit("hello")
        # my_worker.finished.connect(self.xxx)
        self.threadPool.append(my_thread)
        self.my_worker = my_worker
class GenericWorker(QtCore.QObject):
    start = pyqtSignal(str)
    finished = pyqtSignal()
    def __init__(self, function, *args, **kwargs):
        super(GenericWorker, self).__init__()
        logthread('GenericWorker.__init__')
        self.function = function
        self.args = args
        self.kwargs = kwargs
        self.start.connect(self.run)
    @pyqtSlot()
    def run(self, *args, **kwargs):
        logthread('GenericWorker.run')
        self.function(*self.args, **self.kwargs)
        self.finished.emit()
# run
app = QtGui.QApplication(sys.argv)
test = MyApp()
test.show()
app.exec_()
the ouput is:
mainwin.__init__         : MainThread, 140221684574016,
GenericWorker.__init__   : MainThread, 140221684574016,
GenericWorker.run        : Dummy-1, 140221265458944,
mainwin.addBatch         : Dummy-1, 140221265458944,
mainwin.add              : Dummy-1, 140221265458944,
mainwin.add              : Dummy-1, 140221265458944,
mainwin.add              : Dummy-1, 140221265458944,
mainwin.add              : Dummy-1, 140221265458944,
mainwin.add              : Dummy-1, 140221265458944,
mainwin.add              : Dummy-1, 140221265458944,
 
     
     
     
     
     
     
    