在Qt C ++应用程序中嵌入Widget时,PyQt5 Connect无法正常工作

时间:2015-11-24 06:21:05

标签: python-3.x pyqt5 qt5.4

我正在尝试创建一个应用程序,用户可以在其中创建屏幕(.ui并使用pyuic5.bat生成相应的ui_.py文件) 然后在PyQt5中为它们编写脚本(在.py文件中)。 我想在我的基于Qt的C ++应用程序中嵌入这些python脚本,这些脚本将加载这些脚本(因为我的应用程序的其余部分在Qt中)。

我能够将用户创建的这些屏幕嵌入到应用程序中,但由于一些奇怪的原因,我可以将#34; connect"写在脚本内部失败。 [我已经尝试过计时器超时,但仍然没有拨打电话。 ]

有人可以告诉我为什么会发生这种情况,或者至少是一种获取调试日志的方法,这可能有助于我了解出现了什么问题。

ui_Form1.py:

from PyQt5 import QtCore, QtGui, QtWidgets

class Ui_Form(object):
    def setupUi(self, Form):
        Form.setObjectName("Form")
        Form.resize(400, 300)
        self.pushButton = QtWidgets.QPushButton(Form)
        self.pushButton.setGeometry(QtCore.QRect(40, 60, 75, 23))
        self.pushButton.setObjectName("pushButton")
        self.pushButton_2 = QtWidgets.QPushButton(Form)
        self.pushButton_2.setGeometry(QtCore.QRect(170, 60, 75, 23))
        self.pushButton_2.setObjectName("pushButton_2")

        self.retranslateUi(Form)
        QtCore.QMetaObject.connectSlotsByName(Form)

    def retranslateUi(self, Form):
        _translate = QtCore.QCoreApplication.translate
        Form.setWindowTitle(_translate("Form", "Form"))
        self.pushButton.setText(_translate("Form", "PushButton"))
        self.pushButton_2.setText(_translate("Form", "PushButton"))

Form1.py:

import sys
sys.dont_write_bytecode = True

from PyQt5 import QtCore, QtGui, QtWidgets

from ui_Form1 import Ui_Form

class Form(QtWidgets.QWidget):
    def __init__(self, parent=None):
        super(Form, self).__init__(parent)
        self.ui=Ui_Form();
        self.ui.setupUi(self)
        self.ui.pushButton.clicked.connect(self.changeColor)

    def changeColor(self):
        self.ui.pushButton_2.setStyleSheet( "background-color: rgb(255, 255, 0); " )

if __name__ == '__main__':
    app = QtWidgets.QApplication(sys.argv);
    ex = Form();
    ex.show();
    sys.exit(app.exec_())

简单的Qt-C ++代码,基本上使用Sip嵌入脚本:

#include <Python.h>
#include <QApplication>
#include <QLayout>
#include <QWidget>
#include <QMessageBox>
#include <QFileInfo>
#include <QXmlStreamReader>
#include <QMainWindow>
#include <QDesktopWidget>

PyObject* call_function(PyObject *callable, PyObject *args)
{
    PyObject *result = NULL, *pArgs;

    if (callable == NULL)
    {
        return NULL;
    }

    if (PyCallable_Check(callable))
    {
        if (args == NULL)
            pArgs = PyTuple_New(0);
        else
            pArgs = args;

        result = PyObject_CallObject(callable, pArgs);

        if (args == NULL)
            Py_XDECREF(pArgs);
            // pDict and pFunc are borrowed and must not be Py_DECREF-ed.

        if (result == NULL)
        {
            PyErr_Clear();
        }
    }

    return result;
}

int main(int argc, char *argv[])
{
    QApplication app(argc, argv);

    if( argc < 3 ){
        QMessageBox::warning( 0 , "Error" , "Pass Name of File as argument\n eg. <exe Name>.exe <Full FileName(.py)> <ClassName>" );
        exit(0);
    }

    QWidget *parentWidget = new QWidget;
    parentWidget->setWindowTitle( "HMI - Viewer");

    Py_DontWriteBytecodeFlag = 1;
    Py_Initialize();

    QFileInfo objFile( argv[1] );
    QString strFileName = objFile.baseName();
    QString strFilePath = objFile.absolutePath();
    QString strClassName = argv[2];

    PyRun_SimpleString("import os, sys\n");
    PyRun_SimpleString(QString("sys.path.append('"+QString(strFilePath)+"')\n").toStdString().c_str());

    PyObject *pyModule = PyImport_ImportModule(strFileName.toStdString().c_str());

    if (!pyModule) {
        QMessageBox::warning( 0 , "Error" , "Cannot create module" );
        return 1;
    }

    PyObject *pyDict = PyModule_GetDict(pyModule);
    /* pDict is a borrowed reference */

    Py_XDECREF(pyModule);


    QString strString = QString(
                QString("import PyQt5.QtGui, PyQt5.QtWidgets, sip\n"
                                 "def __embedded_factory__wrap_widget__(parentPtr):\n"
                                 "    parent = sip.wrapinstance(parentPtr, PyQt5.QtWidgets.QWidget)\n"
                                 "    return parent\n"
                                 "def __embedded_factory__create__(parent):\n"
                                 "    widget = " ) + strClassName + QString("(parent)\n"
                                 "    return sip.unwrapinstance(widget)\n" )
                );

    PyRun_String(strString.toStdString().c_str(), Py_file_input, pyDict, pyDict);
    PyObject *pyWrapper = PyDict_GetItemString(pyDict, "__embedded_factory__wrap_widget__");
    PyObject *pyFactory = PyDict_GetItemString(pyDict, "__embedded_factory__create__");

    if (!pyFactory || !pyWrapper) {
        QMessageBox::warning( 0 , "Error" , "Could Not create pyFactory or pyWrapper" );
        return 2;
    }

    PyObject *wrapperArgs = PyTuple_New(1);
    PyObject *pyParentWidgetPtr = PyLong_FromVoidPtr(parentWidget);
    PyTuple_SetItem(wrapperArgs, 0, pyParentWidgetPtr);

    PyObject *pyParentWidget = call_function(pyWrapper, wrapperArgs);
    Py_XDECREF(pyWrapper);
    Py_XDECREF(wrapperArgs);

    PyObject *args = PyTuple_New(1);
    PyTuple_SetItem(args, 0, pyParentWidget);

    QGridLayout *layout = new QGridLayout(parentWidget);
    layout->setContentsMargins(0, 0, 0, 0);

    PyObject *pyWidgetPtr = call_function(pyFactory, args);

    if (pyWidgetPtr)
    {
        // Extract the C++ pointer from the PyObject.
        QWidget *widget = (QWidget*)PyLong_AsVoidPtr(pyWidgetPtr);
        if( widget){
        }else{
            QMessageBox::warning( 0 , "Error" , "Position17- Widget NOT Created" );
        }
        Py_XDECREF(pyWidgetPtr);
        layout->addWidget(widget, 0, 0);
    }
    else
    {
        QMessageBox::warning( 0 , "Error" , "Could not create Widget instance" );
        return 2;
    }

    Py_XDECREF(args);
    Py_XDECREF(pyFactory);

    QRect objRect = QApplication::desktop()->screenGeometry();
    objRect.setY(objRect.y() + 20 );
    objRect.setHeight(objRect.height() - 10 - 45 );
    parentWidget->setGeometry(objRect);
    parentWidget->show();
    int result = app.exec();

    Py_Finalize();
    return result;
}

运行应用程序: Test.exe D:/Test/Form1.py表单

正在考虑的系统是 - Windows 7,64位机器,PyQt5,Qt 5.4.0(64位),MSVC 2012

PS:如果我直接使用Python运行这些脚本,那么这些脚本可以很好地工作,因为它们是简单的PyQt5脚本。

e.g。 python.exe D:/Test/Form1.py表单 工作正常(即pushButton_2的颜色颜色发生变化)

0 个答案:

没有答案