我正在尝试创建一个应用程序,用户可以在其中创建屏幕(.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的颜色颜色发生变化)