Python-QML集成#

本教程提供了一步一步的快速浏览,展示了如何加载并交互一个QML文件的应用程序。QML是一种声明式语言,它允许您比C++等传统语言更快地设计UI。QtQml和QtQuick模块提供基于QML的UI所需的基础结构。

在本教程中,您将学习如何将Python与QML应用程序集成。这种机制将帮助您了解如何将Python作为后端,以响应QML界面中UI元素发出的某些信号。此外,您还将学习如何使用Qt Quick Controls 2中的一个特性为您的QML应用程序提供现代的外观。

本教程基于一个允许您设置许多文本属性的应用程序,例如增加字体大小、更改颜色、更改样式等。在开始之前,请安装PySide6 Python包。

以下逐步过程将引导您了解基于QML的应用程序和PySide6集成的关键元素。

  1. 首先,让我们从以下基于QML的UI开始

    ../../_images/textproperties_default.png

    设计基于GridLayout,包含两个ColumnLayout。在UI中,您将找到许多RadioButtonButton和一个Slider

  2. 有了QML文件,您可以通过Python加载它

     1
     2if __name__ == '__main__':
     3    app = QGuiApplication(sys.argv)
     4    QQuickStyle.setStyle("Material")
     5    engine = QQmlApplicationEngine()
     6
     7    # Get the path of the current directory, and then add the name
     8    # of the QML file, to load it.
     9    qml_file = Path(__file__).parent / 'view.qml'
    10    engine.load(qml_file)
    11
    12    if not engine.rootObjects():
    13        sys.exit(-1)
    14
    

    注意,我们只需要一个QQmlApplicationEngine来加载QML文件。

  3. 定义Bridge类,包含将要注册到QML的所有逻辑

     1# To be used on the @QmlElement decorator
     2# (QML_IMPORT_MINOR_VERSION is optional)
     3QML_IMPORT_NAME = "io.qt.textproperties"
     4QML_IMPORT_MAJOR_VERSION = 1
     5
     6
     7@QmlElement
     8class Bridge(QObject):
     9
    10    @Slot(str, result=str)
    11    def getColor(self, s):
    12        if s.lower() == "red":
    13            return "#ef9a9a"
    14        elif s.lower() == "green":
    15            return "#a5d6a7"
    16        elif s.lower() == "blue":
    17            return "#90caf9"
    18        else:
    19            return "white"
    20
    21    @Slot(float, result=int)
    22    def getSize(self, s):
    23        size = int(s * 34)
    24        if size <= 0:
    25            return 1
    26        else:
    27            return size
    28
    29    @Slot(str, result=bool)
    30    def getItalic(self, s):
    31        if s.lower() == "italic":
    32            return True
    33        else:
    34            return False
    35
    36    @Slot(str, result=bool)
    37    def getBold(self, s):
    38        if s.lower() == "bold":
    39            return True
    40        else:
    41            return False
    

    注意,注册过程得益于QmlElement装饰器,它底层使用对Bridge类的引用以及变量QML_IMPORT_NAMEQML_IMPORT_MAJOR_VERSION

  4. 现在,回到QML文件,并将信号连接到在Bridge类中定义的槽

    Bridge {
       id: bridge
    }
    

    ApplicationWindow内部,我们声明一个与Python类同名组件,并提供一个id:。这个id将帮助您获取从Python注册的元素的引用。

     1            RadioButton {
     2                id: italic
     3                Layout.alignment: Qt.AlignLeft
     4                text: "Italic"
     5                onToggled: {
     6                    leftlabel.font.italic = bridge.getItalic(italic.text)
     7                    leftlabel.font.bold = bridge.getBold(italic.text)
     8                    leftlabel.font.underline = bridge.getUnderline(italic.text)
     9
    10                }
    11            }
    

    属性ItalicBoldUnderline是互斥的,这意味着任何时候只能有一个处于激活状态。为了实现这一点,每次我们选择这些选项之一时,我们都通过如您在上文小段中看到的那样,通过QML元素属性检查这三个属性。其中只有一个将返回True,而其他两个将返回False,这就是我们确保只有一个应用于文本的方法。

  5. 每个槽都会验证选定的选项是否包含与属性关联的文本

    1    @Slot(str, result=bool)
    2    def getItalic(self, s):
    3        if s.lower() == "italic":
    4            return True
    5        else:
    6            return False
    

    返回TrueFalse允许您激活和关闭QML UI元素的属性。

    还可以返回其他不是Boolean类型的值,例如负责返回字体大小的槽

    1    @Slot(float, result=int)
    2    def getSize(self, s):
    3        size = int(s * 34)
    4        if size <= 0:
    5            return 1
    6        else:
    
  6. 现在,要更改我们应用程序的外观,您有两个选项

    1. 使用命令行:执行python文件时添加选项,--style

      python main.py --style material
      
    2. 使用一个qtquickcontrols2.conf文件

       1[Controls]
       2Style=Material
       3
       4[Universal]
       5Theme=System
       6Accent=Red
       7
       8[Material]
       9Theme=Dark
      10Accent=Red
      

      然后将其添加到您的.qrc文件中

      1<!DOCTYPE RCC><RCC version="1.0">
      2<qresource prefix="/">
      3    <file>qtquickcontrols2.conf</file>
      4</qresource>
      5</RCC>
      

      运行,pyside6-rcc style.qrc -o style_rc.py,生成rc文件。最后,从您的main.py脚本中导入它。

    1import sys
    2from pathlib import Path
    3
    4from PySide6.QtCore import QObject, Slot
    5from PySide6.QtGui import QGuiApplication
    6from PySide6.QtQml import QQmlApplicationEngine, QmlElement
    7from PySide6.QtQuickControls2 import QQuickStyle
    8
    9import style_rc
    

    您可以在这里了解更多有关此配置文件的信息。

    您应用程序的最终外观将是这样

    ../../_images/textproperties_material.png

您可以通过view.qmlmain.py尝试此示例。