Python和C++混合使用QML开发GUI

31 篇文章 9 订阅
本文介绍了如何使用Python的PyQt、C++和QML结合开发图形用户界面。通过Python调用QML的函数并传递变量,以及QML调用Python的方法,实现了双向通信。同时,提到了在不同编辑环境中如Eclipse+PyDev、Eric和QtCreator进行代码编辑的场景。参考了多个资源,详细讲解了Python中QML函数的调用和信号槽的使用。
摘要由CSDN通过智能技术生成

pyqt和qml结合的中文资很少,在baidu上搜索,基本上就是浪费时间。在国外的blog上,有零星的几篇,但是介绍好的少。在stackoverflow上看到一篇关于pyside,发现pyside,发现pyside果然给力,那就开始我们的pyside游戏之旅吧。

【编辑器】
目前的编辑环境是,Eclipse+PyDev, Erics, QtCreator这三个工具一起使用。用前两者进PY代码编辑,用QtCreator进行QML编辑和设计。

【概要】
用PyQt,C++,QML实现一个简单但的文本输入框值得取得和设置。从编码角度来看,我们需要在Python中调用QML的function方法,并通过参数传递把python中设定的变量值给QML.需要在QML中调用Python定义的函数方法,并把QML中InputText的Text值传递给Python.无论控件和业务逻辑多复杂都是如此。

Python代码



import sys
from PySide import QtCore, QtDeclarative,  QtGui

class QtInterface(QtCore.QObject):
    signaller_in_txt = QtCore.Signal(str)
    signaller_out_txt = QtCore.Signal()
    
     def __init__(self):
        QtCore.QObject.__init__(self)
        self.in_txt = "test"

     #@的这种声明方式,会在后面的部分介绍,并且参考链接中,有一篇文也介绍的很清晰。

     #这是一个不带参数的Slot函数。                
    @QtCore.Slot()
    def getInputText(self):
        print self.in_txt        

     #这个一个带参数的Slot函数,我们就是利用这个参数,在QML中,调用这个函数,并把InputText的text值发送过来,并且在函数中,打印出这个传递值。
    @QtCore.Slot(str)
    def setInputText(self, text):
        print text
        
     #在updateValues函数中,通过信号发射,调用QML中的function函数,并将对控件的设置值,传递过去。信号变量声明,在类中,和与对应的QML函数简历毁掉联系,是在main函数中完成的。
    def updateValues(self):
#        self.signaller_in_txt.emit(str(self.in_txt))
        self.signaller_out_txt.emit()

        
#MainView是主要View视图,继承了基类,QDeclarativeView,继承了最大化,最小话和关闭窗体的机能。
class MainView(QtDeclarative.QDeclarativeView):
    def __init__(self,  parent=None):
          #构造父类
        super( MainView,  self).__init__(parent)
          #设定窗体Title内容
        self.setWindowTitle("Counter")
          #设定与本地QML关联
        self.setSource( QtCore.QUrl.fromLocalFile('abc.qml'))
          #设定窗体尺寸变化的模式,继承了父类的模式
        self.setResizeMode( QtDeclarative.QDeclarativeView.SizeRootObjectToView)


#创建一个QtGui的应用实例
qApplication = QtGui.QApplication(sys.argv)
#主视图创建
window = MainView()
#显示主视图
window.show()

#取得用于解析QML的类实例
qcontext = window.rootContext()
interface = QtInterface()
#将用户自己的QtObject子类和窗体类建立连接
qcontext.setContextProperty("qInterface",  interface)

#将信号和QML函数建立映射关联。
interface.signaller_score_a.connect(window.rootObject().updateScoreA)
interface.signaller_in_txt.connect(window.rootObject().updateInText)
interface.signaller_out_txt.connect(window.rootObject().getInTxt)

#退出应用
sys.exit(qApplication.exec_())


QML代码

QML语言基本UI元素的描述信息和功能函数,QML本身可以通过自己的函数定义执行来完成一定程度上功能,完全和背后的语言(C++,Python)脱离关系。而且在很多的平台上使用,甚至包括移动平台,可以和我的WEB服务器很好的链接,传递数据。



import QtQuick 1.1

Rectangle {
    id: rectangle1
    width: 480
    height: 272

    gradient: Gradient {
        GradientStop {
            id: gradientStop1
            position: 0
            color: "#ffffff"
        }

        GradientStop {
            position: 1
            color: "#abc09f"
        }
    }
    //UML中的函数,要通过emit发射信号调用。
    function updateInText(string) {
        in_txt.text = string
    }

    function updateIn() {
        in_txt.text = "ozzy"
    }
    //在Python中,通过emit调用getInTxt函数
    function getInTxt() {
         //console.log基本就是JavaScript的用法。
        console.log("debug")
        return (in_txt.text)
    }


    Text {
        id: score_a
        x: 150
        y: 74
        width: 131
        height: 48
        text: qsTr("Text")
        verticalAlignment: Text.AlignVCenter
        font.pixelSize: 12
    }

    MouseArea {
        id: a_scored
        x: 303
        y: 200
    }

    Rectangle {
        id: team_a
        x: 150
        y: 148
        width: 127
        height: 46
        color: "#4e3a3a"
        radius: 10

        TextInput {
            id: team_a_txt
            x: 24
            y: 13
            width: 80
            height: 20
            text: qsTr("A")
            selectionColor: "#316cc4"
            horizontalAlignment: TextInput.AlignHCenter
            font.pixelSize: 12
        }

        MouseArea {
            id: team_a_score_ma
            x: 1
            y: 0
            width: 126
            height: 46
            onClicked: {
                qInterface.aScored()
            }
        }
    }

    TextInput {
        id: in_txt
        x: 345
        y: 67
        width: 80
        height: 20
        text: qsTr("InputText")
        selectionColor: "#316cc4"
        font.pixelSize: 12

        MouseArea {
            id: in_txt_ma
            x: -17
            y: 77
            width: 115
            height: 57
            z: 2
          //直接在MouseArea中添加对应的事件处理
            onClicked: {
               //qInterface是在Python中建立的映射关系,通过这个对象实例,就可以直接调用Python中的函数方法,并且可以传递参数               
                qInterface.setInputText(in_txt.text)
     //下面的这个函数被注释掉了,因为getText()是一个C++写的方法
     //console.log(qInterface.getText())
            }
        }

    }

    Rectangle {
        id: get_in_text
        x: 322
        y: 148
        width: 127
        height: 46
        color: "#4e3a3a"
        radius: 10

        Text {
            id: text1
            x: 38
            y: 15
            width: 40
            height: 16
            text: qsTr("Enter")
            font.pixelSize: 12
        }
    }
}

C++代码



#ifndef LOGIN_H
#define LOGIN_H


#include <QObject>

class Login: public QObject
{
    Q_OBJECT
public:
     //Q_INVOKABLE关键字,可以让QML直接调用C++方法。相当于 濮阳天python中的@QtCore.Slot()
     Q_INVOKABLE QString getText(void) const;
    Login(QObject *parent = 0);
    virtual ~Login();
signals:
    void setInputText(const QString &s);
public slots: 
    void setText(const QString &s);
};
#endif // LOGIN_H

#include "login.h"
Login::Login(QObject *parent)
      :QObject(parent)
  {
    QObject::connect(this, SIGNAL(setInputText(QString)), this, SLOT(setText(QString)));
  }

    Login::~Login() {
    }

  QString LS::getText(void) const
  {
      return "from C++ Code";
  }
  void LS::setText(const QString &s) {
      qDebug("this is string.");
      qDebug("%s", s.toLocal8Bit().data());
  }


【后记】
上面的代码可以看到,PyQt和C++公用一个QML代码,QML几乎不变(不是几乎,就是一样的)。
PyQT(PySide)更适应快速开发,写Python也更好玩。用C++实现性能要求比较高的共同部分,则更有优势。

Python中QML调用Python函数,只要把python的函数声明为@QtCore.Slot
Python调用QML函数,需要定义信号和connect QML的函数。

C++是,UML调用C++函数,只要把C++函数声明过为Q_INVOKABLE
C++调用QML函数,需要声明Signal和Connect Slot函数。

这点Python和C++的流程保持一致。

【参考】
http://qt-project.org/wiki/PySide

在QML中使用JavaScript和Sqlite
http://thierry-xing.iteye.com/blog/1387855

关于QML中调用qt类中的信号,槽,成员函数,属性做记录 
http://huangchunquanmaker.blog.163.com/blog/static/107408483201104101331193/

Connecting Qt signal to QML function 
http://blog.chinaunix.net/uid-12664992-id-129937.html

@符号在python中的作用
http://ar.newsmth.net/thread-8f2dbaba27a86d-1.html

Filling and reading QML UI forms from python.
http://qt-project.org/wiki/Filling-and-reading-QML-UI-forms-from-Python

转载出处: http://upblog.sinaapp.com/topic/46/python%E5%92%8Cc-%E6%B7%B7%E5%90%88%E4%BD%BF%E7%94%A8qml%E5%BC%80%E5%8F%91gui

Qt中调用Python脚本程序可以使用QProcess类,而在qml控件和Python脚本程序之间的通信可以使用Python的标准输入输出流。以下是一个简单的示例: main.cpp: ```c++ #include <QCoreApplication> #include <QProcess> int main(int argc, char *argv[]) { QCoreApplication a(argc, argv); QProcess *process = new QProcess(&a); process->setProgram("python"); process->setArguments(QStringList() << "script.py"); QObject::connect(process, &QProcess::readyReadStandardOutput, [&]() { QString output = process->readAllStandardOutput(); qDebug() << "Python output: " << output; }); process->start(); return a.exec(); } ``` script.py: ```python print("Python script is running...") while True: input_str = input() if input_str == "quit": break print("Received input: " + input_str) ``` Qml中可以使用Qt的QProcess类或PyQt的QProcess类来调用Python脚本程序,也可以使用PyQt的QPythonRunner类直接运行Python代码。在qml中与Python脚本程序之间的通信可以使用Python的标准输入输出流。 例如,使用Qt的QProcess类: ```qml import QtQuick 2.0 Item { id: root Button { text: "Run Python script" onClicked: { var process = Qt.createQmlObject('import QtQuick 2.0; import QtQuick.Controls 2.0; Process { program: "python"; arguments: ["script.py"]; }', root); process.readyReadStandardOutput.connect(function() { var output = process.readAllStandardOutput(); console.log("Python output: " + output); }); process.start(); } } } ``` 使用PyQt的QProcess类: ```qml import QtQuick 2.0 import PyQt5.QtCore 1.0 import PyQt5.QtGui 1.0 import PyQt5.QtWidgets 1.0 Item { id: root Button { text: "Run Python script" onClicked: { var process = new QProcess(); process.setProgram("python"); process.setArguments(["script.py"]); process.readyReadStandardOutput.connect(function() { var output = process.readAllStandardOutput(); console.log("Python output: " + output); }); process.start(); } } } ``` 使用PyQt的QPythonRunner类: ```qml import QtQuick 2.0 import PyQt5.QtCore 1.0 import PyQt5.QtGui 1.0 import PyQt5.QtWidgets 1.0 Item { id: root Button { text: "Run Python code" onClicked: { var runner = new QPythonRunner(); runner.runCode("print('Hello from Python!')"); runner.readyReadStandardOutput.connect(function() { var output = runner.readAllStandardOutput(); console.log("Python output: " + output); }); } } } ```
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值