PyQt Note

PyQt notes

1. PyQt5 QML 界面

.py

from PyQt5.QtGui import QGuiApplication
from PyQt5 import QtQml

if __name__ == '__main__':

    path = 'QtQuick/test/qml/main.qml'
    app = QGuiApplication([])
    engine = QtQml.QQmlApplicationEngine()
    engine.load(path)
    app.exec_()

main.qml

import QtQuick 2.12
import QtQuick.Controls 2.12



ApplicationWindow {
    id: test
    visible: true
    width: 400; height: 700
    color: "#ffffff"
    Text {
        text: "hello world!";
    }

    

    Button{
        id: btn
        property alias cellColor1: btnColorRect.color//cunstom var/property

        text: "你好hello";
        font.family: "Alibaba puhuiti"; 
        font.pointSize: 13; 
        // background.color: "#aacccc"
        background: Rectangle {
            id: btnColorRect
            anchors.fill: parent
            color: "#8000ff"

        }
        anchors.centerIn: parent
        MouseArea{
            anchors.fill: parent
            hoverEnabled: true
            onEntered:{ 
                btnColorRect.color = "#0000ff"
                }
            onExited: {
                btnColorRect.color = "#8000ff"
                }
        }

    }

    Grid {
        id: colorGrid
        // x: 4; 
        anchors{
            horizontalCenter: parent.horizontalCenter
            bottom: parent.bottom
            bottomMargin: 4
        }
        rows: 2; columns: 3; spacing: 3

        MyColorPicLabel { cellColor: "red"; onClicked: btnColorRect.color = cellColor }
        MyColorPicLabel { cellColor: "green"; onClicked: btnColorRect.color = cellColor }
        MyColorPicLabel { cellColor: "blue"; onClicked: btnColorRect.color = cellColor }
        MyColorPicLabel { cellColor: "yellow"; onClicked: btnColorRect.color = cellColor }
        MyColorPicLabel { cellColor: "steelblue"; onClicked: btnColorRect.color = cellColor }
        MyColorPicLabel { cellColor: "#ff0080"; onClicked: btnColorRect.color = cellColor }

    }
    
}

MyColorPicLabel.qml

import QtQuick 2.4


Item {
    id: container
    property alias cellColor: rectangle.color//cunstom var/property
    signal clicked(color cellColor)//singal

    width: 70; height: 40

    Rectangle {
        id: rectangle
        border.color: "#380071"
        border.width: 2
        anchors.fill: parent
    }

    MouseArea {
        anchors.fill: parent
        hoverEnabled: true
        onClicked: container.clicked(container.cellColor)//触发信号
        onEntered:{
            // console.log("hello");
            rectangle.border.width = 4
        }
        onExited:{
            // console.log("no hello");
            rectangle.border.width = 2
        }
    }
}

2. QML 与 Python Class 互通

python class 定义要点

  • 需要继承 QObject 类
  • __init__() 函数需要调用父类的 构造函数
  • QML 里调用的函数必须是槽函数,用 @pyqtSlot(…) 修饰
class MyScreen(QObject):
    screens = QGuiApplication.screens()
    screenCount = 0

    def __init__(self) -> None:
        super().__init__()  # 调用父类的__init__() 这样才能加载该类至 QML 里
        self.screens = QGuiApplication.screens()
        for i in self.screens:
            self.screenCount += 1

    @pyqtSlot(int, result=QRect)
    def getScreenSize(self, id):
        """[getScreenSize]

        Args:
            id ([int]): [id of screen]

        Returns:
            [QRect]: [screen's size]
        """
        if(id >= self.screenCount or id < 0):
            return QRect(0,0,0,0)
        return self.screens[id].geometry()

    @pyqtSlot(result=str) # 使用pyqtSlot() 修饰该函数,这样 QML 里才能知道函数的参数与返回值
    def test(self):
        return "我是python槽函数传递的字符串"

    @pyqtSlot(str)
    def printlog(self, str):
        print(str)

将python class 加载进 QML

# create screen obejct
scr = MyScreen()
# 注册 Python 类至 QML 根节点
engine.rootContext().setContextProperty("scr", scr)

这样QML 里可以使用 scr 对象了。

QML 信号定义和触发

定义信号

ApplicationWindow {
    id: mainWin
    // signal
    signal myLogSignal(string log)
    ....
}

触发信号

Button{
    text: "点我输出log";
    font.family: "Alibaba puhuiti"; 
    font.pointSize: 13; 
    
    anchors.horizontalCenter: parent.horizontalCenter
    anchors.bottom: btn1.top 
    anchors.bottomMargin: 10
    MouseArea{
        anchors.fill: parent
        onClicked:{
            mainWin.myLogSignal("我是QML 里信号发来的字符串")
        }
    }
}

QML 信号绑定 Python 槽函数

# QML 信号连接 Python 槽函数
my_obj = engine.rootObjects()[0]    # 获取根节点
my_obj.myLogSignal.connect(scr.printlog)    # 绑定信号和槽

Python 调用QML 函数

定义函数

ApplicationWindow {
	...
  	function qmlLog(str){
        console.log(str);
    }
    ....
}

python 调用

# QML 信号连接 Python 槽函数
my_obj = engine.rootObjects()[0]    # 获取根节点
# 调用QML 函数
my_obj.qmlLog("我是qml 函数输出的字符串")

源码

main.py

from PyQt5.QtCore import QObject, QRect, pyqtSlot
from PyQt5 import QtQml
from PyQt5.QtGui import QGuiApplication


class MyScreen(QObject):
    screens = QGuiApplication.screens()
    screenCount = 0

    def __init__(self) -> None:
        super().__init__()  # 调用父类的__init__() 这样才能加载该类至 QML 里
        self.screens = QGuiApplication.screens()
        for i in self.screens:
            self.screenCount += 1

    @pyqtSlot(int, result=QRect)
    def getScreenSize(self, id):
        """[getScreenSize]

        Args:
            id ([int]): [id of screen]

        Returns:
            [QRect]: [screen's size]
        """
        if(id >= self.screenCount or id < 0):
            return QRect(0,0,0,0)
        return self.screens[id].geometry()

    @pyqtSlot(result=str) # 使用pyqtSlot() 修饰该函数,这样 QML 里才能知道函数的参数与返回值
    def test(self):
        return "我是python槽函数传递的字符串"

    @pyqtSlot(str)
    def printlog(self, str):
        print(str)



if __name__ == '__main__':
    path = 'QtQuick/grabImage/qml/main.qml'
    app = QGuiApplication([])
    engine = QtQml.QQmlApplicationEngine()

    # create screen obejct
    scr = MyScreen()
    # 注册 Python 类至 QML 根节点
    engine.rootContext().setContextProperty("scr", scr)

    engine.load(path)

    # QML 信号连接 Python 槽函数
    my_obj = engine.rootObjects()[0]    # 获取根节点
    my_obj.myLogSignal.connect(scr.printlog)    # 绑定信号和槽

    # 调用QML 函数
    my_obj.qmlLog("我是qml 函数输出的字符串")
    
    app.exec_()

main.qml

import QtQuick 2.12
import QtQuick.Controls 2.12



ApplicationWindow {
    id: mainWin
    visible: true
    width: 400; height: 700
    color: "#ffffff"

    // signal
    signal myLogSignal(string log)

    Text {
        text: "hello world!";
    }

    Button{
        id: btn
        property alias cellColor1: btnColorRect.color//cunstom var/property

        text: "你好hello";
        font.family: "Alibaba puhuiti"; 
        font.pointSize: 13; 
        // background.color: "#aacccc"
        background: Rectangle {
            id: btnColorRect
            anchors.fill: parent
            color: "#8000ff"

        }
        anchors.centerIn: parent
        MouseArea{
            anchors.fill: parent
            hoverEnabled: true
            onEntered:{ 
                btnColorRect.color = "#0000ff"
                }
            onExited: {
                btnColorRect.color = "#8000ff"
                }
            onPressed: {
                btnColorRect.color = "#800008"
            }
            onClicked:{
                // grabWin.setFlags(Qt::FramelessWindowHint)
                console.log("hello world");

            }
        }
    }


    Button{
        id: btn1
        font.family: "Alibaba puhuiti"; 
        font.pointSize: 13; 
        text: "点我输出屏幕2分辨率";
        property rect sereen_size: scr.getScreenSize(1) // get size of screen 2

        
        anchors.horizontalCenter: parent.horizontalCenter
        anchors.bottom: btn.top 
        anchors.bottomMargin: 10
        MouseArea{
            anchors.fill: parent
            onClicked:{
                console.log("x =", parent.sereen_size.x)
                console.log("y =", parent.sereen_size.y)
                console.log("width =", parent.sereen_size.width)
                console.log("height =", parent.sereen_size.height)
            }
        }
    }
    Button{
        text: "点我输出log";
        font.family: "Alibaba puhuiti"; 
        font.pointSize: 13; 
        
        anchors.horizontalCenter: parent.horizontalCenter
        anchors.bottom: btn1.top 
        anchors.bottomMargin: 10
        MouseArea{
            anchors.fill: parent
            onClicked:{
                mainWin.myLogSignal("我是QML 里信号发来的字符串")
            }
        }
    }
    Grid {
        id: colorGrid
        // x: 4; 
        anchors{
            horizontalCenter: parent.horizontalCenter
            bottom: parent.bottom
            bottomMargin: 4
        }
        rows: 2; columns: 3; spacing: 3

        MyColorPicLabel { cellColor: "red"; onClicked: btnColorRect.color = cellColor }
        MyColorPicLabel { cellColor: "green"; onClicked: btnColorRect.color = cellColor }
        MyColorPicLabel { cellColor: "blue"; onClicked: btnColorRect.color = cellColor }
        MyColorPicLabel { cellColor: "yellow"; onClicked: btnColorRect.color = cellColor }
        MyColorPicLabel { cellColor: "steelblue"; onClicked: btnColorRect.color = cellColor }
        MyColorPicLabel { cellColor: "#ff0080"; onClicked: btnColorRect.color = cellColor }

    }


    function qmlLog(str){
        console.log(str);
    }
    
}

MycolorPicLabel.qml

import QtQuick 2.4


Item {
    id: container
    property alias cellColor: rectangle.color//cunstom var/property
    signal clicked(color cellColor)//singal

    width: 70; height: 40

    Rectangle {
        id: rectangle
        border.color: "#380071"
        border.width: 2
        anchors.fill: parent
    }

    MouseArea {
        anchors.fill: parent
        hoverEnabled: true
        onClicked: container.clicked(container.cellColor)//触发信号
        onEntered:{
            // console.log("hello");
            rectangle.border.width = 4
        }
        onExited:{
            // console.log("no hello");
            rectangle.border.width = 2
        }
    }
}

本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!