QML 快速上手3 - QuickControl2

QuickControl2


简介

quickcontrol 用于快速构建风格化的用户界面

它包括了以下几个预制的组件风格

  • Default QT 默认风格
  • Universal windows 桌面风格
  • Material 谷歌推出的 MaterialDesign 风格
  • Fusion
  • Imagine

风格设置

官方文档对于风格设置提供了两种方式,此处就采用其中的一种,即使用 QQuickStyle

首先在 pro 文件内,添加对应库
QT += quick quickcontrols2

之后来到 main.cpp 设置我们的整体风格
注意,风格必须在 qml 初始化前设置,且一旦设置则全局使用此风格,不可变换!

#include <QGuiApplication>
#include <QQmlApplicationEngine>

// 第一步,导入头文件
#include <QQuickStyle>


int main(int argc, char *argv[])
{
#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
    QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
#endif

    QGuiApplication app(argc, argv);

    // 第二步,应用风格
    // 这里使用了google的material风格
    QQuickStyle::setStyle("Material");

    ...

    return app.exec();
}

最后回到我们的 qml 主文件,写一段简单的代码测试一下风格

main.qml 代码清单

import QtQuick 2.12
import QtQuick.Controls 2.12

// 默认此处根组件应该是Window,我这里用了ApplicationWindow,效果是一致的
ApplicationWindow {
    visible: true
    width: 640
    height: 480

    // 创建一个列表,包含三个单选按钮
    Column {
        anchors.centerIn: parent
        RadioButton { text: qsTr("Small") }
        RadioButton { text: qsTr("Medium");  checked: true }
        RadioButton { text: qsTr("Large") }
    }
}

如下图展示效果,风格成功应用上去了!

在这里插入图片描述


control 配置文件

对于普通项目,为便于开发,我们可以额外新建一个配置文件用于管理当前应用的整体风格

在与 main.qml 同级的目录下新建配置文件 qtquickcontrols2.conf (必须是这个名字!)

填入下方配置

; This file can be edited to change the style of the application
; Read "Qt Quick Controls 2 Configuration File" for details:
; http://doc.qt.io/qt-5/qtquickcontrols2-configuration.html

; 配置全局风格为MaterialDesign2
[Controls]
Style=Material

图像浏览器案例

推荐风格选择 Fusion

功能很简单,添加菜单栏和工具栏,选择文件并打开;
主要关注点为 FileDialog 的使用

下面是 main.qml 的完整代码

import QtQuick 2.12
import QtQuick.Controls 2.12
import QtQuick.Dialogs 1.2

ApplicationWindow {
    visible: true
    width: 640
    height: 480
    title: qsTr("Image Viewer")

    // 顶部菜单栏
    menuBar: MenuBar {
        // 主菜单项
        Menu {
            title: qsTr("&File")
            // 子菜单项
            MenuItem {
                text: qsTr("&Open...")
                icon.name: "document-open"
                // 点击后触发对应FileDialog
                onTriggered: fileOpenDialog.open()
            }
        }

        Menu {
            title: qsTr("&Help")
            MenuItem {
                text: qsTr("&About...")
                onTriggered: aboutDialog.open()
            }
        }
    }

    // 顶部工具栏
    header: ToolBar {
        // 流式布局
        Flow {
            anchors.fill: parent
            // 工具项
            ToolButton {
                text: qsTr("Open")
                icon.name: "document-open"
                onClicked: fileOpenDialog.open()
            }
        }
    }

    // 设置背景颜色
    background: Rectangle {
        color: "darkGray"
    }

    // 图片显示组件
    Image {
        id: image
        anchors.fill: parent
        fillMode: Image.PreserveAspectFit
        asynchronous: true
    }

    // 打开文件对话框
    FileDialog {
        id: fileOpenDialog
        title: "Select an image file"
        folder: shortcuts.documents
        nameFilters: [
            "Image files (*.png *.jpeg *.jpg)",
        ]
        onAccepted: {
            image.source = fileOpenDialog.fileUrl
        }
    }

    // About对话框
    Dialog {
        id: aboutDialog
        title: qsTr("About")
        Label {
            anchors.fill: parent
            text: qsTr("QML Image Viewer\nA part of the QmlBook\nhttp://qmlbook.org")
            horizontalAlignment: Text.AlignHCenter
        }

        standardButtons: StandardButton.Ok
    }
}

运行结果

在这里插入图片描述


component 组件报错问题

当我们在需要使用 Component 定义一个组件时,通常会发现编辑器报错 Unknown component (M300)

解决方法很简单,点击编辑器菜单栏的 工具->QML/JS->重置代码模型 即可解决

在这里插入图片描述


StackView

StackView 可以实现多页面的堆栈管理,类似于 android 中的 view


下方代码实现效果:点击界面实现 push 和 pop 效果,并附带自定义界面切换效果

由于要使用动画过渡属性,故导入头文件时,control 需要使用 1.4 版本的 import QtQuick.Controls 1.4

简要介绍下方代码展示的主要内容及其对应含义:

  • initialItem 设置初始展示页面/组件
  • delegate 设置当新页面 push 或者被 pop 后的过渡动画
  • Component 组件,根据 id 被 stackview 使用

代码清单 main.qml

import QtQuick 2.12

// 请使用1.4版本
import QtQuick.Controls 1.4

ApplicationWindow {
    visible: true
    width: 640
    height: 480
    title: qsTr("Image Viewer")

    StackView {
        id:sv
        anchors.fill: parent
        initialItem: mainView   // 设置初始页面

        // 设置页面push或pop后过渡动画
        // 动画设置中有两个可用变量:exitItem正在退出的元素;enterItem正在加入的元素;
        delegate: StackViewDelegate {
            // 当动画结束后,执行的对应方法
            function transitionFinished(properties)
            {
                properties.exitItem.x = 0
                properties.exitItem.rotation = 0
            }

            // push插入动画
            // 动画内容是:让当前组件从界面左侧移动走,然后自身再旋转360度
            pushTransition: StackViewTransition {
                // 顺序动画
                SequentialAnimation {
                    ScriptAction {
                        script: enterItem.rotation = 90
                    }
                    PropertyAnimation {
                        target: enterItem
                        property: "x"
                        from: enterItem.width
                        to: 0
                    }
                    PropertyAnimation {
                        target: enterItem
                        property: "rotation"
                        from: 90
                        to: 0
                    }
                }
                PropertyAnimation {
                    target: exitItem
                    property: "x"
                    from: 0
                    to: -exitItem.width
                }
            }

            // pop弹出动画
            // 动画内容:组件颜色渐变(非常实用,建议copy)
            popTransition: StackViewTransition {
                PropertyAnimation {
                    target: enterItem
                    property: "opacity"
                    from: 0
                    to: 1
                }
                PropertyAnimation {
                    target: exitItem
                    property: "opacity"
                    from: 1
                    to: 0
                }
            }
        }

        // 在stackview内部定义组件
        Component{
            id: mainView
            MouseArea{
                Rectangle{
                    id:mvRect
                    width: 100; height: 100
                    anchors.centerIn: parent
                    color: "orange"
                }
                onClicked: sv.push(sideView) // 点击后插入新页面
            }
        }

        // 定义的另一个组件
        Component{
            id: sideView
            MouseArea{
                Rectangle{
                    id:svRect
                    width: 100; height: 100
                    anchors.centerIn: parent
                    color: "deepskyblue"
                }
                onClicked: sv.pop() // 点击后弹出当前页面
            }
        }
    }
}

外部界面文件调用案例

注意,这里全部需要使用 import QtQuick.Controls 2.2

当然了,我们不可能把所有组件或者页面都以 Component 的形式写到 stackview 里面去,我们需要对其进行充分的解构

首先来看看主文件 main.qml

import QtQuick 2.12
import QtQuick.Controls 2.2

ApplicationWindow {
    visible: true
    width: 640
    height: 480
    title: qsTr("Image Viewer")

    StackView {
        id:sv
        anchors.fill: parent
        // 加载外部组件HomeView
        initialItem: HomeView{}
    }
}

主页面代码清单 HomeView.qml

import QtQuick 2.0
import QtQuick.Controls 2.2

// Page表示页面
Page{
    title: qsTr("Home")

    MouseArea{
        anchors.fill: parent
        Label {

            text: qsTr("Home Screen")
        }
        // sv就是我们在主页面定义的stackview组件
        // push内部直接写同级目录下的qml文件,就可以插入了
        onClicked: sv.push("SideView.qml")
    }
}

副页面代码清单 SideView.qml

import QtQuick 2.0
import QtQuick.Controls 2.2

Page{
    title: qsTr("Home")

    Button{
        id:btn
        width: 120; height: 40
        anchors.centerIn: parent
        text: qsTr("点击返回home")
        onClicked: sv.pop() // 弹出
    }
}

这里就实现了调用外部 qml 文件来执行 push 和 pop 操作


SwipeView

类似前端中的轮播图

同样的,需要注意导入 import QtQuick.Controls 2.2

import QtQuick 2.9
import QtQuick.Controls 2.2

ApplicationWindow {

    // ...

    visible: true
    width: 640
    height: 480

    title: qsTr("Side-by-side")

    // 滑动视图
    SwipeView {
        id: swipeView
        anchors.fill: parent

        // 这是三个外部Page组件,用于组成视图
        Current {
        }

        UserStats {
        }

        TotalStats {
        }

        // ...

    }

    // 导航指示点
    PageIndicator {
        anchors.bottom: parent.bottom
        anchors.horizontalCenter: parent.horizontalCenter

        currentIndex: swipeView.currentIndex
        count: swipeView.count
    }

    // ...

}

我们随机找一个 swipeview 用到的外部组件,该组件很简单,根部是 Page,点击按钮返回第一个轮播项

代码清单 TotalStats.qml

import QtQuick 2.9
import QtQuick.Controls 2.2

// 和stackview一样,这里的外部组件依然需要使用page定义
Page {
    header: Label {
        text: qsTr("Community Stats")
        font.pixelSize: Qt.application.font.pixelSize * 2
        padding: 10
    }

    Column {
        anchors.centerIn: parent
        spacing: 10
        Label {
            anchors.horizontalCenter: parent.horizontalCenter
            text: qsTr("Community statistics")
        }
        Button {
            anchors.horizontalCenter: parent.horizontalCenter
            text: qsTr("Back")
            onClicked: swipeView.setCurrentIndex(0); // 点按钮回到第一个轮播项
        }
    }
}

由于内容比较简单,其余的两个轮播项就不一一展示代码了,反正也就是对应的使用 Page 组件即可!


  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Zhillery

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值