4

PyQt + QML 快速开发GUI总结

 2 years ago
source link: https://www.linuxzen.com/pyqt-qml-kuai-su-kai-fa-guizong-jie.html
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

如何和PyQt交互

QML和PyQt交互主要有三种方法: PyQt渲染数据, 信号传递, QML提供接口

使用PyQt显示QML

要想在Python里使用PyQt来调用QML显示, 需要用到 PyQt4.QtDeclarative.QDeclarativeView 实例的 setSource 将一个 PyQt4.QtCore.QUrl 对象传递进去, 然后调用 PyQt4.QtDeclarative.QDeclarativeView 对象的 show 方法, 下面是一个例子:

from PyQt4.QtDeclarative import QDeclarativeView
from PyQt4.QtGui import QApplication
from PyQt4.QtCore import QUrl

app = QApplication([])

view = QDeclarativeView()
view.setSource(QUrl("/path/to/demo.qml"))
view.show()

app.exec_()

通过PyQt渲染数据到QML

渲染QML变量有两种方法, 一种是QML中没有定义的变量, 一种是在QML中已经定义好的变量, 第一种是预定义变量, 第二种是设置变量

预定义变量

PyQt4.QtDeclarative.QDeclarativeView 的 rootContext 方法会返回一个QML上下文, 通过这个对象可以对QML进行一些变量的预定义

注意, 预定义变量必须在 setSource 调用之前进行, 还有如果是字符串类型如要使用 PyQt4.QtCore.QString 进行转换, 数字可以不用转换, 如果是列表或字典需要使用 PyQt4.QtCore.QVariant 进行转换, 下面是一个例子:

test.qml:

import Qt 4.7

Rectangle {
    id: test
    width: 100; height: 30

    Text {
        anchors.fill:parent;
        text: textData;
    }
}

test.py:

from PyQt4.QtDeclarative import QDeclarativeView
from PyQt4.QtGui import QApplication
from PyQt4.QtCore import QUrl, QString


app = QApplication([])

view = QDeclarativeView()
rootContext = view.rootContext()
rootContext.setContextProperty("textData", QString("hi"))
view.setSource(QUrl("test.qml"))
view.show()
app.exec_()

如果将 rootContext 两行移到 view.setSource 下面, QML里将找不到对 textData 的引用

如果QML里已经定义好了变量, 而我们就可以在PyQt里对它进行更改, 对QML里的变量更改需要使用 PyQt4.QtDeclarative.QDeclarativeView 对象的 rootObject 方法返回的 rootObject 对象, 调用 rootObject 对象的 setProperty 方法即可对QML里变量做出更改

注意, 使用 rootObject 对QML的更改必须在 setSource 之后, 否则 rootObject 方法将返回 None, 下面是一个例子

test.qml:

import Qt 4.7

Rectangle {
    id: test
    property string textData;
    width: 100; height: 30

    Text {
        anchors.fill:parent;
        text: textData;
    }
}

test.py:

from PyQt4.QtDeclarative import QDeclarativeView
from PyQt4.QtGui import QApplication
from PyQt4.QtCore import QUrl, QString


app = QApplication([])

view = QDeclarativeView()
view.setSource(QUrl("test.qml"))
rootObject = view.rootObject()
rootObject.setProperty("textData", QString("hi"))
view.show()
app.exec_()

上面例子我们在QML定义了 textData 变量, 并在 setSource 之后使用 rootObject 的 setProperty 对 textData 变量进行了更改

QML信号的传递

QML有信号机制, 可以在QML之间使用JavaScript进行触发和接收, 当然也可以将信号传递给后端的PyQt, 我们在此不讨论QML内部的信号, 我们仅讨论QML信号传递到PyQt这部分, QML使用signal创建信号, 信号可以携带参数, 使用调用函数的方法可以触发信号, 下面是一个例子:

test.qml

import Qt 4.7

Rectangle {
    id: test;

    signal mclicked;   // 定义信号

    Text {
        anchors.fill:parent;
        text: "Click Me"
    }

    MouseArea {
        onClicked: {
            mclicked();  // 触发信号
        }
    }
}

上面我们定义了一个 mclicked 的信号, 并且在点击时会触发这个信号, PyQt 可以通过 rootObject 获取这个信号, 并为这个信号绑定槽:

test.py

from PyQt4.QtDeclarative import QDeclarativeView
from PyQt4.QtGui import QApplication
from PyQt4.QtCore import QUrl, QString


app = QApplication([])

view = QDeclarativeView()
view.setSource(QUrl("test.qml"))
def on_click():
    print "hi"

rootObject = view.rootObject()
rootObject.mclicked.connect(on_click)
view.show()
app.exec_()

上面为QML的 mclicked 信号绑定了一个函数, 当点击QML窗体时, 控制台就会输出 hi

QML提供接口

上面我们定义了信号, 如果响应信号仅仅在控制台输出没有意义, 我们可以通过QML在顶级元素定义JavaScript函数 向PyQt提供接口, 下面是例子:

test.qml

import Qt 4.7

Rectangle {
    id: test;

    signal mclicked;   // 定义信号

    Text {
        id: testText
        anchors.fill:parent;
        text: "Click Me"
    }

    MouseArea {
        onClicked: {
            mclicked();  // 触发信号
        }
    }

    function set_text(text){
        testText.text = text
    }
}

上面我们在QML顶级元素定义了一个 set_text 函数, 接下来我们就可以通过 rootObject 进行调用

test.py

from PyQt4.QtDeclarative import QDeclarativeView
from PyQt4.QtGui import QApplication
from PyQt4.QtCore import QUrl, QString


app = QApplication([])

view = QDeclarativeView()
view.setSource(QUrl("test.qml"))

def on_click():
    rootObject.set_text("Clicked")

rootObject = view.rootObject()
rootObject.mclicked.connect(on_click)
view.show()
app.exec_()

上面我们用响应信号的槽, 通过 rootObject 调用QML提供的函数接口, 当点击窗体时, 显示文字会从 Click Me 变成 Clicked, 当然这仅仅是个例子, 这种响应可以在QML里直接完成

import Qt 4.7

Rectangle {
    id: test;

    signal mclicked;   // 定义信号

    Text {
        id: testText
        anchors.fill:parent;
        text: "Click Me"
    }

    MouseArea {
        onClicked: {
            mclicked();  // 触发信号
        }
    }

    function set_text(){
        testText.text = "Clicked"
    }

    Component.onCompleted : {
        mclicked.connect(set_text);  // 在加载完成后为mclicked信号绑定槽
    }
}

About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK