【问题标题】:Call pyqt widget from Qt widgets application从 Qt 小部件应用程序调用 pyqt 小部件
【发布时间】:2019-09-05 04:45:39
【问题描述】:

我正在尝试使用 python 脚本插件扩展我的 Qt 应用程序。 如果我调用任何非 pyqt 脚本,它工作正常。 如果我从 c++ 函数调用任何 pyqt 脚本,它也可以正常工作,但我在 Qt Widget 应用程序之外。类似的东西:

#include "/usr/include/python3.5m/Python.h"

int CargaPlugins(const char* ruta, const char* nombremodulo, const char* nombrefuncion);


int main(int argc, char** argv)
{
    std::string path = "PYTHONPATH=";
    path.append(argv[1]);
    putenv ((char*)path.c_str());
    Py_Initialize();
    CargaPlugins(argv[1],"plugin_loader","iniciar");
    Py_Finalize();
    return 0;
}


int CargaPlugins(const char* ruta, const char* nombremodulo, const char* nombrefuncion)
{
    PyObject *pName, *pModule, *pDict, *pFunc;
    PyObject *pArgs, *pValue;
    pName = PyUnicode_DecodeFSDefault(nombremodulo);
    /* Error checking of pName left out */
    pModule = PyImport_Import(pName);
    Py_DECREF(pName);

    if (pModule != NULL)
    {
        pFunc = PyObject_GetAttrString(pModule, nombrefuncion);
        /* pFunc is a new reference */

        if (pFunc && PyCallable_Check(pFunc))
        {
            pArgs = PyTuple_New(1);
            pValue = PyUnicode_FromString(ruta);
            if (!pValue)
            {
                Py_DECREF(pArgs);
                Py_DECREF(pModule);
                fprintf(stderr, "Cannot convert argument\n");
                return 1;
            }
            /* pValue reference stolen here: */
            PyTuple_SetItem(pArgs, 0, 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");
                return 1;
            }
        }
        else
        {
            if (PyErr_Occurred())
                PyErr_Print();
            fprintf(stderr, "Cannot find function \"%s\"\n", nombrefuncion);
        }
        Py_XDECREF(pFunc);
        Py_DECREF(pModule);
    }
    else
    {
        PyErr_Print();
        fprintf(stderr, "Failed to load \"%s\"\n", nombremodulo);
        return 1;
    }
}

还有pyqt5模块:

plugin_loader.py

#!/usr/bin/python
# -*- coding: utf-8 -*-

import imp
import os
import sys
from PyQt5 import QtCore, QtGui, QtWidgets
from DialogoImprimir import DialogoImprimir

def iniciar(ruta):
    import sys  
    if not hasattr(sys,'argv'):
        sys.argv = []
    app = QtWidgets.QApplication(sys.argv)
    myapp = DialogoImprimir(getPlugins(ruta))
    myapp.show()    
    sys.exit(app.exec_())

DialogoImprimir.py

class DialogoImprimir(QtWidgets.QDialog):
    def __init__(self, datos):
        QtWidgets.QDialog.__init__(self)
        self.datos = datos
        self.GeneraUI(datos)
        -------------------

好吧,我的问题是,如果我将 C++ int CargaPlugins(const char* ruta, const char* nombremodulo, const char* nombrefuncion) 像函数一样插入到我的 Qt Widgwets 应用程序中,调用时会出现此错误:

QCoreApplication::exec: 事件循环已经在运行

我认为解决方案是将当前 QApplication 的指针传递给 python 脚本,或者如果有任何方法可以做到这一点,则在脚本 python 运行时获取当前 QApplication 并使用它,但我没有不知道怎么做。

编辑:

我在Qt内部调用函数时的代码sn-p:

ma​​inwindow.cpp

void MainWindow::ActionImprimir()
{
    Imprimir impresor("/home/user/pathofpythonmodules/","plugin_loader","iniciar");

imprimir.cpp

Imprimir::Imprimir(const char* ruta, const char* nombremodulo, const char* nombrefuncion)
{
    std::string path = "PYTHONPATH=";
    path.append(ruta);
    putenv ((char*)path.c_str());
    Py_Initialize();
    pFuncion = CargarPlugins(ruta,nombremodulo,nombrefuncion);
    if (pFuncion)
    {
        //more things
    }
}   

(和 CargarPlugins() 和之前的函数一样)

【问题讨论】:

  • 您可以展示如何在 Qt 应用程序中调用此函数
  • 谢谢@eyllanesc,我已经编辑了问题

标签: python c++ qt pyqt pyqt5


【解决方案1】:

由于您有一个 QApplication,因此无需创建另一个,因此解决方案是:

#!/usr/bin/python
# -*- coding: utf-8 -*-

import importlib
import os
import sys
from PyQt5 import QtCore, QtGui, QtWidgets
from DialogoImprimir import DialogoImprimir

def iniciar(ruta):
    app = QtWidgets.QApplication.instance()
    if app is None:
        app = QtWidgets.QApplication([])
    myapp = DialogoImprimir(getPlugins(ruta))
    return myapp.exec_()

一个完整的例子你可以找到here

【讨论】:

  • 非常感谢@eyllanesc。如果不仅仅是一个答案,您的完整示例!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-10-30
  • 1970-01-01
相关资源
最近更新 更多