如何在嵌入式Python中使用QT应用程序
问题描述:
我正在将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();
}
答
这个答案是通用的,并且可能不是可行的与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()应该只允许一个事件运行下一个要运行的事件调用列表,否则它将不会返回,直到处理完所有事件。
如果我理解正确,那么您希望在Python中调用一个方法,在经过一段延迟后会回调您的应用程序。最简单的方法是创建后台线程,轮询事件队列或等待条件变量。然后,你的主线程会将事件插入后台线程监视的队列中 - 当执行事件时,后台线程将执行该事件。 – brandx 2011-06-23 06:40:24