簡體   English   中英

如何在 QT 應用程序中的嵌入式 Python 中休眠

[英]How to sleep in an embedded Python in a QT-application

我將 Python 嵌入到 GUI QT 應用程序中。 我為我的 UI 文件中的一個按鈕分配了一個信號,當它被單擊時,我運行腳本。

這在使用來自的方法時有效

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();
}

這個答案很籠統,可能不適用於 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); }

請注意,它是一個好主意 function 返回程序實際休眠的時間而不是輸入值。 您可能需要在代碼中知道這段時間。

此 function 將由 python 調用

但是,對於 GUI 環境,您還希望繼續檢查和運行可能發生的任何事件,此 function 不會這樣做。

所以你需要一個新的 function 看起來像這樣:

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() function 的方法,您應該查看 QT 文檔,此解決方案應該可以解決您的問題。

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

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

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM