QML Options

理解你的需求,以下是 QML 中顶层容器的不同类型,以及它们适用于哪些场景:

顶层容器类型

$$ApplicationWindow 用途:适用于创建应用程序的主窗口,带有内置的菜单栏和状态栏。 导入模块:QtQuick.Controls Window 用途:用于创建没有内置菜单栏和状态栏的窗口。可以手动添加所需的控件。 导入模块:QtQuick.Window Dialog 用途:用于创建对话框窗口,通常用于提示用户进行某些操作或输入信息。 导入模块:QtQuick.Controls Popup 用途:用于创建弹出窗口,可以用于上下文菜单、工具提示等。 导入模块:QtQuick.Controls Item 用途:最基本的可视化对象容器,不创建窗口,但可以作为其他元素的父容器。 导入模块:QtQuick Rectangle 用途:用于创建简单的矩形区域,常用于布局和装饰。 导入模块:QtQuick Application 用途:通常作为 QML 应用程序的根对象,管理整个应用程序的生命周期。 导入模块:QtQuick$$

示例代码

以下是每个顶层容器的简单示例:

1. ApplicationWindow

import QtQuick 6.2
import QtQuick.Controls 6.2

ApplicationWindow {
    visible: true
    width: 800
    height: 600
    title: "ApplicationWindow Example"
}

2. Window

import QtQuick 6.2
import QtQuick.Window 6.2

Window {
    visible: true
    width: 800
    height: 600
    title: "Window Example"
}

3. Dialog

import QtQuick 6.2
import QtQuick.Controls 6.2

Dialog {
    visible: true
    width: 400
    height: 300
    title: "Dialog Example"
    standardButtons: Dialog.Ok | Dialog.Cancel
}

4. Popup

import QtQuick 6.2
import QtQuick.Controls 6.2

Popup {
    visible: true
    width: 200
    height: 100
    Text {
        anchors.centerIn: parent
        text: "Popup Example"
    }
}

5. Item

import QtQuick 6.2

Item {
    width: 800
    height: 600
    Rectangle {
        width: 100
        height: 100
        color: "blue"
    }
}

6. Rectangle

import QtQuick 6.2

Rectangle {
    width: 800
    height: 600
    color: "lightgray"
    Text {
        anchors.centerIn: parent
        text: "Rectangle Example"
    }
}

7. Application

import QtQuick 6.2

Application {
    id: app
    Item {
        width: 800
        height: 600
        Rectangle {
            width: 100
            height: 100
            color: "blue"
        }
    }
}

顶层容器结构

顶层容器的结构通常如下:

Application 或 ApplicationWindow 或 Window 或 Dialog 或 Popup
    子元素:Item, Rectangle, Text, Button, ListView 等各种 UI 元素

示例:

ApplicationWindow {
    visible: true
    width: 800
    height: 600
    title: "App Structure Example"

    Rectangle {
        width: parent.width
        height: parent.height
        color: "lightgray"

        Text {
            anchors.centerIn: parent
            text: "Hello, World!"
        }
    }
}

这些顶层容器类型及其结构可以根据具体需求选择和使用,从而满足不同类型的应用程序设计需求。

关键字:Property

让我们深入探讨一下 QML 中 property 的作用、外部访问的机制,以及如何决定属性是否暴露给外部。

1. QML 中的属性访问机制

内置属性(如 heightwidth 等)

  • 内置属性:QML 中的某些属性,如 heightwidthcolor 等,是组件自带的内置属性,这些属性默认是对外暴露的。因此,父组件可以直接访问和设置这些属性。

  • 访问方式:这些内置属性在定义组件时自动提供,可以直接通过组件的 id 在外部访问,例如:

Rectangle {
    id: rect
    width: 100
    height: 50
}

Item {
    width: rect.width  // 直接访问 rect 的 width 属性
}

2. property 的作用

定义自定义属性

  • 扩展属性:通过 property,你可以定义组件的自定义属性,这些属性不是组件的内置属性。property 使得这些自定义属性能够被外部访问和修改。例如,你可能会定义一个 property 来跟踪某个状态:
Rectangle {
    id: rect
    property int myCustomHeight: 100
}

Item {
    width: rect.myCustomHeight  // 访问自定义的 myCustomHeight 属性
}

绑定和初始值

  • 属性绑定property 可以与其他属性或表达式绑定,这使得属性之间能够自动更新。例如:
Rectangle {
    id: rect
    property int myCustomHeight: width / 2  // myCustomHeight 随着 width 的变化而变化
    width: 200
}

暴露内部状态

  • 状态管理:你可以通过 property 把组件的内部状态暴露给外部,从而实现更好的封装和模块化设计。例如,定义一个 property 来暴露内部的计算结果:
Rectangle {
    id: rect
    property real area: width * height  // 暴露矩形的面积
}

3. 内部变量与 property 的区别

  • 局部变量:如果你只需要在组件内部使用某个值或状态,通常不会使用 property,而是使用局部变量或 JavaScript 变量。局部变量不会暴露给外部,也不会通过 id 访问到。

    • 局部变量示例
      Rectangle {
          id: rect
          width: 100
          height: 50
          var internalValue = 200  // 只在这个组件内部可见的变量
      }
      
  • property 的作用property 主要用于定义和管理组件的外部可见状态或配置。通过 property,你可以把组件的某些内部状态暴露出来,供父组件或外部组件访问。

4. 总结:property 的功能与外部访问

  • 外部访问:内置属性(如 heightwidth)默认是暴露给外部的,而通过 property 定义的属性也会暴露给外部。没有 property 修饰的局部变量则不会被外部访问到。

  • property 的用途property 主要用于定义组件的自定义属性、管理属性绑定、或暴露内部状态给外部。property 还允许你为自定义属性设置初始值,并支持动态绑定。

  • 局部变量 vs property:如果你不希望某个状态或值被外部访问,且只需要在组件内部使用,那么应使用局部变量或 JavaScript 变量,而不是 propertyproperty 用于那些需要外部访问和管理的属性。

通过理解这些概念,你可以更好地设计和组织 QML 代码,确保组件之间的低耦合性和良好的封装性。

003.Singleton 单例对象

使用场景

  1. 可以是要在外部动态的设置某一个程序的属性,让整个程序的其他组件都因此做出改变,可以用singleton

    QML Styling 及 Singleton 使用方法浅谈 - 掘金

  2. 希望精简,模块不要反复被创建

【必要步骤】在相应的qml文件的顶行写pragma Singleton

pragma Singleton

注意这条语句要写在import 语句之前

【必要步骤】需要在相应的CMakeList.txt里设置QT_QML_SINGLETON_TYPE 为TRUE

set_source_files_properties(First_Color_Scheme.qml PROPERTIES
    QT_QML_SINGLETON_TYPE TRUE
)
  • 在哪一个CMakeList.txt呢?

    我的qml文件处在项目根目录下的一个叫content的文件夹中

    这个文件夹是专门存放所有qml文件的

    在content下有一个CMakeList.txt

    (不要放到项目根目录下的CMakeList.txt里面-因为放进去也没用)

  • 设置完会怎么样,请看build之后的目录下:

    build\6_5_3_MSVC2019_x64-Debug\qml\content\qmldir

    Untitled

  • 设置技巧

    本语句的位置不能低于qt6_add_qml_module(或qt_add_qml_module)

    Untitled

【必要步骤】需要在相应的CMakeList.txt里创建单例模块Singleton Module(独立于其他QML模块)

  • CMakeLists.txt的相关代码
qt6_add_qml_module(singleton
    URI "singleton"
    VERSION 1.0
    QML_FILES
        Color/First_Color_Scheme.qml
)

这里的URI很重要,最后我们要调用的地方,都需要import,而import后面的模块名称就是看URI的。

为什么一定要再这里创建单例模块呢?

按照微软的文档:

singleton.png

我们就是需要去把它做成一个模块的

【必要步骤】调用singleton object(单例对象)的办法

  • 不能用的办法1:创建它

    • 代码

      Second_TitleBar {
          id: bID_Instance_Module_TitleBar
          anchors.top: parent.top
          width: parent.width
      }
      
    • 例如这种方法,就是去创建一个单例对象,这样会提示错误

      Untitled

    • 错误信息

      11:00:01: Starting C:\Code\ASCtl\PL\QtProj\build\6_5_3_MSVC2019_x64-Debug\ASCtl_UIApp.exe...
      DLL_PROCESS_ATTACH: The DLL has been attached to the process at 00007FF902D40000
      QML debugging is enabled. Only use this in a safe environment.
      Ext_CreateAudioControl called.
      ASCtl_Impl constructor called.
      QQmlApplicationEngine failed to load component
      qrc:/qt/qml/Main/main.qml:7:1: Type App unavailable
      qrc:/qt/qml/content/App.qml:54:1: Type VolumeMixer unavailable
      qrc:/qt/qml/content/VolumeMixer.qml:20:5: Composite Singleton Type Second_TitleBar is not creatable.
      DLL_PROCESS_DETACH: The DLL has been detached from the process at 00007FF902D40000
      11:00:01: C:\Code\ASCtl\PL\QtProj\build\6_5_3_MSVC2019_x64-Debug\ASCtl_UIApp.exe exited with code -1
      
  • 可能可以用的办法:把某个要作为单例的qml封装成一个module

    具体是在content/CMakeList.txt下,用qt6_add_qml_module去新建一个模块

    然后去import这个模块,例如import titlebar 1.0 / import controlpanel 1.0这样

    不过这个办法我也没有尝试过。

  • 需要注意:调用时要加入Component.onCompleted: {

    已经在多处都看见这种做法了

    QML中如何实现一个单例-QT开发中文网

    可能谈到调用就是异步的。

相关的帖子

Singletons in QML | Qt QML 6.7.2

Singleton QML failed to load as module

How to make a QML Component a Singleton?

Qt 创建 单例/Singleton qml 文件_pragma singleton-CSDN博客

004. QML中的signal & slot

要点:

  • 1.信号要在本qml文件中的顶层容器中进行定义 就算触发信号的位置是在本qml文件中嵌套的component里面,也都要在顶层容器中进行定义
rectangle{
    ...
    signal Sig_Name_XXX
    ...
}
  • 2.信号的使用必须加圆括号(),可以不必加分号;,否则会发不出去

signal Sig_Name_XXX()
  • 3.信号的传递必须一层一层的传上去(若你是一层一层的封装好模块的话) 因为信号的接受者只能识别被它创建的那一个对象里面信号

container: Image

Property:

sourceSize.width: 
sourceSize.height: 

this property was used for recapture the source and made a new image internally. if image.width & image.height are illegal value(e.g,. 0), the sourceSize will have the original size of this picture.

005. enum Qt::WindowType & flags Qt::WindowFlags

    // flags: Qt.Window | Qt.CustomizeWindowHint
    // flags: Qt.Window | Qt.FramelessWindowHint | Qt.WindowMinimizeButtonHint | Qt.WindowMaximizeButtonHint

    //设置无框的窗口
    flags: Qt.Window | Qt.FramelessWindowHint 
    // flags: Qt.Window | Qt.CustomizeWindowHint | Qt.WindowTitleHint

enum Qt::WindowType flags Qt::WindowFlags

它的逻辑是首先判断是什么窗口类型,可选项有

1. Widget
2. Window
3. Dialog
4. Sheet
5. Drawer //outdated
6. Popup
7. Tool
8. ToolTip
9. SplashScreen
10. SubWindow
11. ForeignWindow
12. CoverWindow

所以这12种是所有的窗口类型

选择完我要的窗口Window,之后,我就可以进一步选择窗口标志

$$FramelessWindowHint CustomizeWindowHint$$

当然flag可是不止这两种,但是目前我就主要用到了这两种,所以其他的以后再补充啦哈哈

第一种就是无边框的窗体

第二种就是自定义的窗体

第二种接下来还有许多options是配合它出现的,也就是说,CustomizeWindowHint只是一个开关