2011-05-27 65 views
1

我正在將Python嵌入到GUI QT應用程序中。我給我的UI文件中的一個按鈕分配了一個信號,當它被點擊時,我運行腳本。如何在嵌入式Python中使用QT應用程序

使用從

http://docs.python.org/py3k/extending/embedding.html

我還添加了一些功能上的嵌入式模塊如在該網頁上5.4節表現出的方​​法時,此工作。我希望能夠在python腳本中添加一些延遲。我如何在不使用睡眠的情況下做到這一點,因爲睡眠會阻止整個應用程序?我想你會用QTimer來做,它會在一段時間後喚醒python腳本,但我無法弄清楚,這是如何完成的。

我相信我非常接近解決方案,所以我不想在可能的情況下添加線程,甚至不需要PythonQT或Boost等其他框架。

這裏的相關片段:

static PyObject* openDoor(PyObject *self, PyObject *args) 
    { 
     int value1 = 0; 
     if (!PyArg_ParseTuple(args, "l", &value1)) 
      return Py_BuildValue("i", -1); 

    opendoor(value1) 
    return PyLong_FromLong(value1); 
} 

static PyObject* mysleep(PyObject *self, PyObject *args) 
{ 
    int value1 = 0; 
    if (!PyArg_ParseTuple(args, "l", &value1)) 
     return Py_BuildValue("i", -1); 
// this does not work !!! 
// QTimer slideShowtimer = new QTimer(this); 
// connect(slideShowtimer, SIGNAL(timeout()), this, SLOT(slideShowHelper())); 
// slideShowtimer->start(5000); 


    return PyLong_FromLong(value1); 
} 


static PyMethodDef EmbMethods[] = { 
     {"openDoor", openDoor, METH_VARARGS, "."}, 
     {"closeDoor", closeDoor, METH_VARARGS, "."}, 
     {"sleep", mysleep, METH_VARARGS, "Sleep."}, 
    {NULL, NULL, 0, NULL} 
}; 

static PyModuleDef EmbModule = { 
    PyModuleDef_HEAD_INIT, "obu", NULL, -1, EmbMethods, 
    NULL, NULL, NULL, NULL 
}; 

static PyObject* 
PyInit_emb(void) 
{ 
    return PyModule_Create(&EmbModule); 
} 

// taken from python docs 
void MainWindow::on_ScriptButton_clicked() 
{ 
    PyObject *pName, *pModule, *pFunc; 
    PyObject *pArgs, *pValue; 
    int i; 

    PyImport_AppendInittab("emb", &PyInit_emb); 
    Py_Initialize(); 

    pName = PyUnicode_FromString("multiply"); 
    pModule = PyImport_Import(pName); 
    Py_DECREF(pName); 

    if (pModule != NULL) { 
     pFunc = PyObject_GetAttrString(pModule, "run"); 

     if (pFunc && PyCallable_Check(pFunc)) { 
      pArgs = PyTuple_New(1); 
      for (i = 0; i < 1; ++i) { 
       pValue = PyLong_FromVoidPtr(this); 
       if (!pValue) { 
        Py_DECREF(pArgs); 
        Py_DECREF(pModule); 
        fprintf(stderr, "Cannot convert argument\n"); 
       } 
       PyTuple_SetItem(pArgs, i, pValue); 
      } 
      pValue = PyObject_CallObject(pFunc, pArgs); 
      Py_DECREF(pArgs); 
      if (pValue != NULL) { 
       printf("Result of call: %ld\n", PyLong_AsLong(pValue)); 
       Py_DECREF(pValue); 
      } 
      else { 
       Py_DECREF(pFunc); 
       Py_DECREF(pModule); 
       PyErr_Print(); 
       fprintf(stderr,"Call failed\n"); 
      } 
     } 
     else { 
      if (PyErr_Occurred()) 
       PyErr_Print(); 
      fprintf(stderr, "Cannot find function \n"); 
     } 
     Py_XDECREF(pFunc); 
     Py_DECREF(pModule); 
     ; 
    } 
    else { 
     PyErr_Print(); 
     fprintf(stderr, "002 Failed to load \n"); 
    } 
    Py_Finalize(); 
} 
+0

如果我理解正確,那麼您希望在Python中調用一個方法,在經過一段延遲後會回調您的應用程序。最簡單的方法是創建後臺線程,輪詢事件隊列或等待條件變量。然後,你的主線程會將事件插入後臺線程監視的隊列中 - 當執行事件時,後臺線程將執行該事件。 – brandx 2011-06-23 06:40:24

回答

0

這個答案是通用的,並且可能不是可行的與Qt框架。 (我不使用QT自己)

睡眠之所以不起作用是它基本上看起來像在C以下代碼++

static PyObject* mysleep(PyObject *self, PyObject *args) 
{ 
    int secs = 0; 
    if (!PyArg_ParseTuple(args, "l", &secs)) 
     return Py_BuildValue("i", -1); 
    long start = gettimestamp(); // This function should return a unix timestamp 
    long now = start; 
    while (now < start + secs) { 
    now = gettimestamp(); } 
    return PyLong_FromLong(now-start); } 

注意它是一個好主意,你函數返回程序實際上休眠多長時間而不是輸入值。因爲您可能需要在代碼中瞭解這段時間。

此功能將被蟒蛇

但是與GUI環境,你也想繼續檢查和運行可能會出現此功能不會做任何事件被調用。

,所以你需要看起來像這樣一個新功能:

static PyObject* mysleep(PyObject *self, PyObject *args) 
{ 
    int secs = 0; 
    if (!PyArg_ParseTuple(args, "l", &secs)) 
     return Py_BuildValue("i", -1); 
    long start = gettimestamp(); // This function should return a unix timestamp 
    long now = start; 
    while (now < start + secs) { 
    handleEvents(); // This function makes the framework check, and run events in they have occurred it will be framework spefic 
    now = gettimestamp(); } 
    return PyLong_FromLong(now-start); } 

你應該檢查QT文件,如果存在一個的方式來實施handleEvents()與QT功能,該解決方案應該解決您的問題。

注意:這會導致計算機至少等待n秒,在正在處理的事件中,它必須在循環再次檢查時間之前完成。

另外handleEvents()應該只允許一個事件運行下一個要運行的事件調用列表,否則它將不會返回,直到處理完所有事件。

相關問題