QML小效果学习笔记

   参考网上一些QML效果的小例子在此做下记录,代码大多由网路各大神提供,自己编译运行,从中对自己不知道的部分,查阅资料后,添加注释,积累经验,望提高。

持续更新...

目录

1.BusyIndicator [等待指示器]

2.任意选择表情

3.图片切成任意形状显示

4.侧边栏平移滑动动画效果

5.模拟微信页面滑动栏

6.侧边滚动条



 

1.BusyIndicator [等待指示器]

QML小效果学习笔记_第1张图片

代码

//main.qml
import QtQuick 2.7
import QtQuick.Controls 2.0
import QtQuick.Layouts 1.0

ApplicationWindow {
    visible: true
    width: 400
    height: 300
    title: qsTr("Qml自定义等待指示器")

    BusyIndicator {
        id: busyIndicator
        anchors.centerIn: parent
        implicitWidth: 96
        implicitHeight: 96
        opacity: running ? 0.0 : 1.0
        contentItem: QmlBusyIndicator{}
    }

    MouseArea{
        anchors.fill: parent
        onClicked: busyIndicator.running = !busyIndicator.running
    }
}

//QmlBusyIndicator.qml
import QtQuick 2.7
import QtGraphicalEffects 1.0

Item {
    //圆形
    Rectangle {
        id: rect
        width: parent.width
        height: parent.height
        color: Qt.rgba(0, 0, 0, 0)
        radius: width / 2
        border.width: width / 6 //为width时表示整个圆,小于width可以切成圆环
        visible: false
    }

    //渐变色
    ConicalGradient {
        width: rect.width
        height: rect.height
        gradient: Gradient {
            GradientStop { position: 0.0; color: "white" }
            GradientStop { position: 1.0; color: "black" }
        }
        source: rect //渐变色作用范围
        //在圆环顶部的小圆形,使其转圈时是个圆头
        Rectangle {
            anchors.top: parent.top
            anchors.horizontalCenter: parent.horizontalCenter
            width: rect.border.width
            height: width
            radius: width / 2
            color: "#000099"
        }

        RotationAnimation on rotation {
            from: 0
            to: 360
            duration: 800
            loops: Animation.Infinite
        }
    }
}

2.任意选择表情

实现方法:gridview/listview 排列表情图片,onEntered事件定位鼠标悬停位置,states状态列表控制选择效果

import QtQuick 2.7
import QtQuick.Controls 2.0
import QtQuick.Layouts 1.0

ApplicationWindow {
    visible: true
    height: gridView.cellHeight+4*2
    width: gridView.cellWidth*12+4*2

    ListModel {
        id: listModel
    }

    Component{
        id: baseListDelegate

        Item {
            id: delegateItem
            height: gridView.cellHeight
            width: gridView.cellWidth

            Rectangle{
                id: delegateItemBack
                anchors.fill: parent
                color : "#AAAAAA"

                MouseArea {
                    anchors.fill: parent
                    hoverEnabled: true  //设置进入mouserarea就发enterd信号
                    onEntered: {
                        console.log("onEntered.",model.index)
                        delegateItem.GridView.view.currentIndex = model.index; //设置currentIndex以改变选中表情的背景色
                    }
                }

                Image {
                    id: image
                    anchors.centerIn: parent
                    source: face
                    width: 32
                    height: 32
                    MouseArea{
                        anchors.fill: parent
                        onClicked: {
                            console.debug(qsTr("选择的名称: ") + face)
                            close()
                        }
                    }
                }
            }
            //delegateItemBack的状态对象列表 when为true时,执行PropertyChanges内容
            states: [
                State {
                    name: "isCurrentItem"
                    when: delegateItem.GridView.isCurrentItem
                    PropertyChanges {
                        target: delegateItemBack; color : "#AAAAAA";
                    }
                },
                State {
                    name: "isNotCurrentItem"
                    when: !delegateItem.GridView.isCurrentItem
                    PropertyChanges {
                        target: delegateItemBack; color : "black";
                    }
                }
            ]
        }
    }

    GridView {
        id: gridView
        anchors.margins: 4
        anchors.fill: parent
        clip: true
        cellWidth: 40
        cellHeight: 40
        model: listModel
        delegate: baseListDelegate
        boundsBehavior: Flickable.StopAtBounds

        Component.onCompleted: {
            listModel.append({"face" : "emoji/Face_(0).png"})
            listModel.append({"face" : "emoji/Face_(1).png"})
            listModel.append({"face" : "emoji/Face_(2).png"})
            listModel.append({"face" : "emoji/Face_(3).png"})
            listModel.append({"face" : "emoji/Face_(4).png"})
            listModel.append({"face" : "emoji/Face_(5).png"})
            listModel.append({"face" : "emoji/Face_(6).png"})
            listModel.append({"face" : "emoji/Face_(7).png"})
            listModel.append({"face" : "emoji/Face_(8).png"})
            listModel.append({"face" : "emoji/Face_(9).png"})
            listModel.append({"face" : "emoji/Face_(10).png"})
            listModel.append({"face" : "emoji/Face_(11).png"})
        }
    }
}

 

3.图片切成任意形状显示

原图

QML小效果学习笔记_第2张图片              QML小效果学习笔记_第3张图片

效果图

QML小效果学习笔记_第4张图片

实现:OpacityMask

import QtQuick 2.7
import QtQuick.Controls 2.0
import QtGraphicalEffects 1.0

ApplicationWindow {
    id:mainWidnow
    width: 400
    height: 300
    color: "grey"
    visible: true

    Item {
        width: 96
        height: 96
        anchors.centerIn: parent
        Image {
            id: sourceimage
            source: "qrc:/qt.png"
            sourceSize: Qt.size(parent.width, parent.height)
            smooth: true
            visible: false
        }

//切圆形
//        Rectangle {
//            id: mask
//            width: parent.width
//            height:parent.height
//            radius: height/2
//            color:"red"
//            visible: false
//        }
        Image {
            id: mask
            sourceSize: Qt.size(parent.width, parent.height)
            source: "qrc:/11.png"
            visible: false
        }

        OpacityMask {
            anchors.fill: sourceimage
            source: sourceimage
            maskSource: mask
        }
    }
}

 

4.侧边栏平移滑动动画效果

效果

QML小效果学习笔记_第5张图片

实现方法:使用Behavior on产生动画效果,使用transform: Translate 通过控制x坐标实现平移滑动

import QtQuick 2.7
import QtQuick.Window 2.2
import QtQuick.Controls 2.0

ApplicationWindow {
    visible: true
    width: 400
    height: 300
    title: qsTr("Qml侧边滑动菜单")
    property bool bMenuShown: false

    Rectangle {
        anchors.fill: parent
        color: "#AAAAAA";
        opacity: bMenuShown ? 1 : 0
        /*
          Behavior动画效果 on:作用于Item的opacity属性 duration变化时间300
         */
        Behavior on opacity {
            NumberAnimation {
                duration: 300
            }
        }
    }

    Rectangle {
        anchors.fill: parent
        color: "#FFFFFF"
        opacity: bMenuShown ? 0.5 : 1
        Behavior on opacity {
            NumberAnimation {
                duration: 300
            }
        }

        Button {
            width: 48
            height: 48
            text: qsTr("菜单")
            onClicked: onMenu();
        }

        /*
        Transform元素是一个基本类型,无法直接实例化,可用的Transform类型有3个:
        Rotation:旋转
        Scale:缩放
        Translate:平移
         */
        transform: Translate {
            id: menuTranslate
            x: 0
            Behavior on x {
                NumberAnimation {
                    duration: 400;
                    easing.type: Easing.OutQuad //动画的缓和曲线设置(Easing.OutQuad减速到0)
                }
            }
        }
        MouseArea {
            anchors.fill: parent
            enabled: bMenuShown
            onClicked: onMenu();
        }
    }

    function onMenu()
    {
        console.log(menuTranslate.x+ ""+bMenuShown)
        menuTranslate.x = bMenuShown ? 0 : width * 0.8//白色rectangle左右平移(x:0~0.8*width)
        bMenuShown = !bMenuShown;
    }
}

 

5.模拟微信页面滑动栏

QML小效果学习笔记_第6张图片

实现方式

上部分使用Swipeview滑动视图,滑动时可收到onCurrentIndexChanged信号,对应切换下方效果。

下部分使用TabBar组合Repeater, 点击时,对应改变上方效果。

//BaseTabBar.qml
import QtQuick 2.7
import QtQuick.Controls 2.0
import QtQuick.Layouts 1.0

TabBar {
    property alias myModel: myModel  //alias
    property int lastIndex: 0

    id: bar
    currentIndex: 0

    ListModel {
        id: myModel
    }

    onCurrentIndexChanged:
    {
        console.log("TabBar index: %d",currentIndex)
        //reset the last clicked Button
        repeater.itemAt(bar.lastIndex).imageSource = myModel.get(bar.lastIndex).modelSrc;
        repeater.itemAt(bar.lastIndex).textColor = myModel.get(bar.lastIndex).modelColor;

        //set the clicked button green
        repeater.itemAt(bar.currentIndex).imageSource = myModel.get(bar.currentIndex).modelSrcG;
        repeater.itemAt(bar.currentIndex).textColor = myModel.get(bar.currentIndex).modelColorG;
        bar.lastIndex = bar.currentIndex;
    }

    Repeater {
        id: repeater
        model: myModel //count of TabButton

        /*
          TabButton is used in conjunction with a TabBar.
        */
        TabButton {
            property alias imageSource: image.source
            property alias textColor: text.color

            height: bar.height
            contentItem:Text{
                id: text
                text: modelText
                horizontalAlignment: Text.AlignHCenter
                verticalAlignment: Text.AlignBottom
                color: (model.index === bar.currentIndex) ? modelColorG : modelColor
            }
            background:Image{
                id: image
                width: 24
                height: 24
                anchors.horizontalCenter: parent.horizontalCenter
                source: (model.index === bar.currentIndex) ? modelSrcG : modelSrc
            }
            onHoveredChanged: {
                if (model.index !== bar.currentIndex){
                    hovered ? text.color = modelColorG : text.color = modelColor
                    hovered ? image.source = modelSrcG : image.source = modelSrc
                }
            }
            onClicked: {
                //reset the last clicked Button
                repeater.itemAt(bar.lastIndex).imageSource = myModel.get(bar.lastIndex).modelSrc;
                repeater.itemAt(bar.lastIndex).textColor = modelColor;

                //set the clicked button green
                image.source = modelSrcG;
                text.color = modelColorG;
                bar.lastIndex = model.index;

                barIndexChanged(currentIndex)
            }
        }
    }
}

//main.qml
ApplicationWindow {
    id: frmWindow
    visible: true
    width: 300
    height: 400

    function barIndexChanged(iIndex)
    {
        console.log("iIndex:"+iIndex)
        view.currentIndex = iIndex
    }

    footer: BaseTabBar{
        id: bar
        height: 48
        width: parent.width
        background: Rectangle{
            color: "#EFEBE7"
        }
        Component.onCompleted: {
            myModel.append({ "modelText": "消息", "modelColor": "#000000", "modelColorG": "#148014", "modelSrc": "qrc:/images/Chat_MsgRecord.svg", "modelSrcG": "qrc:/images/Chat_MsgRecordG.svg"})
            myModel.append({ "modelText": "联系人", "modelColor": "#000000", "modelColorG": "#148014", "modelSrc": "qrc:/images/Chat_FriendManager.svg", "modelSrcG": "qrc:/images/Chat_FriendManagerG.svg"})
            myModel.append({ "modelText": "发现", "modelColor": "#000000", "modelColorG": "#148014", "modelSrc": "qrc:/images/Mobile_Find.svg", "modelSrcG": "qrc:/images/Mobile_FindG.svg"})
            myModel.append({ "modelText": "我", "modelColor": "#000000", "modelColorG": "#148014", "modelSrc": "qrc:/images/Main_P2PChat.svg", "modelSrcG": "qrc:/images/Main_P2PChatG.svg"})
        }
    }

    SwipeView {
        id: view
        height: frmWindow.height - bar.height -10
        width: parent.width

        Rectangle{
            color: "#F5F5F5"
            Text {
                text: qsTr("消息")
                anchors.centerIn: parent
            }
        }
        Rectangle{
            color: "#F5F5F5"
            Text {
                text: qsTr("联系人")
                anchors.centerIn: parent
            }
        }
        Rectangle{
            color: "#F5F5F5"
            Text {
                text: qsTr("发现")
                anchors.centerIn: parent
            }
        }
        Rectangle{
            color: "#F5F5F5"
            Text {
                text: qsTr("我")
                anchors.centerIn: parent
            }
        }
        onCurrentIndexChanged: {
            //直接滑动视图 下方tabBar对应改变
            console.log("-----------view.index:"+currentIndex)
            bar.currentIndex = currentIndex
        }
    }
}

此部分源码下载地址:https://download.csdn.net/download/qq_30042269/10795530


20181121更新

6.侧边滚动条

实现:使用ScrollBar,通过position属性改变,改变TextEdit的位置

ApplicationWindow {
    visible: true
    width: 400
    height: 300

    Rectangle {
          id: frame
          clip: true
          width: parent.width
          height: parent.height
          border.color: "black"
          anchors.centerIn: parent
          anchors.top: parent.bottom
          anchors.left: parent.left
          focus: true

          //键盘上下键 改变滚动条position
          Keys.onUpPressed: vbar.decrease()
          Keys.onDownPressed: vbar.increase()

          TextEdit {
              id: textEdit
              text: "喜欢你啊 喜欢你 喜欢你啊 喜欢你 喜欢你啊 喜欢你 喜欢你啊 喜欢你 喜欢你啊 喜欢你 喜欢你啊 喜欢你 喜欢你啊 喜欢你 喜欢你啊 喜欢你 喜欢你啊 喜欢你 喜欢你啊 喜欢你 喜欢你啊 喜欢你 喜欢你啊 喜欢你 喜欢你啊 喜欢你 喜欢你啊 喜欢你 喜欢你啊 喜欢你 喜欢你啊 喜欢你 喜欢你啊 喜欢你 喜欢你啊 喜欢你 喜欢你啊 喜欢你 喜欢你啊 喜欢你 喜欢你啊 喜欢你 喜欢你啊 喜欢你 喜欢你啊 喜欢你 喜欢你啊 喜欢你 喜欢你啊 喜欢你 喜欢你啊 喜欢你 喜欢你啊 喜欢你 喜欢你啊 喜欢你 喜欢你啊 喜欢你 喜欢你啊 喜欢你 喜欢你啊 喜欢你 喜欢你啊 喜欢你 喜欢你啊 喜欢你 喜欢你啊 喜欢你 喜欢你啊 喜欢你 喜欢你啊 喜欢你 喜欢你啊 喜欢你 喜欢你啊 喜欢你 喜欢你啊 喜欢你 喜欢你啊 喜欢你 喜欢你啊 喜欢你 喜欢你啊 喜欢你 喜欢你啊 喜欢你 喜欢你啊 喜欢你 喜欢你啊 喜欢你 喜欢你啊 喜欢你 喜欢你啊 喜欢你 喜欢你啊 喜欢你 喜欢你啊 喜欢你 喜欢你啊 喜欢你 喜欢你啊 喜欢你 喜欢你啊 喜欢你 喜欢你啊 喜欢你 喜欢你啊 喜欢你 喜欢你啊 喜欢你 喜欢你啊 喜欢你 喜欢你啊 喜欢你 喜欢你啊 喜欢你 喜欢你啊 喜欢你 喜欢你啊 喜欢你 喜欢你啊 喜欢你 喜欢你啊 喜欢你 喜欢你啊 喜欢你 喜欢你啊 喜欢你 喜欢你啊 喜欢你 喜欢你啊 喜欢你 喜欢你啊 喜欢你 喜欢你啊 喜欢你 喜欢你啊 喜欢你 喜欢你啊 喜欢你 喜欢你啊 喜欢你 喜欢你啊 喜欢你 喜欢你啊 喜欢你 喜欢你啊 喜欢你 喜欢你啊 喜欢你 喜欢你啊 喜欢你 喜欢你啊 喜欢你 喜欢你啊 喜欢你 喜欢你啊 喜欢你 喜欢你啊 喜欢你 喜欢你啊 喜欢你 喜欢你啊 喜欢你 喜欢你啊 喜欢你 喜欢你啊 喜欢你 喜欢你啊 喜欢你 喜欢你啊 喜欢你 喜欢你啊 喜欢你 喜欢你啊 喜欢你 喜欢你啊 喜欢你 喜欢你啊 喜欢你 喜欢你啊 喜欢你 喜欢你啊 喜欢你 喜欢你啊 喜欢你 喜欢你啊 喜欢你 喜欢你啊 喜欢你 喜欢你啊 喜欢你 喜欢你啊 喜欢你 喜欢你啊 喜欢你 喜欢你啊 喜欢你 喜欢你啊 喜欢你 喜欢你啊 喜欢你 喜欢你啊 喜欢你 喜欢你啊 喜欢你 喜欢你啊 喜欢你 喜欢你啊 喜欢你 喜欢你啊 喜欢你 喜欢你啊 喜欢你 喜欢你啊 喜欢你 喜欢你啊 喜欢你 喜欢你啊 喜欢你 喜欢你啊 喜欢你 喜欢你啊 喜欢你 喜欢你啊 喜欢你 喜欢你啊 喜欢你 喜欢你啊 喜欢你 喜欢你啊 喜欢你 喜欢你啊 喜欢你 喜欢你啊 喜欢你 喜欢你啊 喜欢你 喜欢你啊 喜欢你 喜欢你啊 喜欢你 喜欢你啊 喜欢你 喜欢你啊 喜欢你 喜欢你啊 喜欢你 喜欢你啊 喜欢你 喜欢你啊 喜欢你 喜欢你啊 喜欢你 喜欢你啊 喜欢你 喜欢你啊 喜欢你 喜欢你啊 喜欢你 喜欢你啊 喜欢你 喜欢你啊 喜欢你 喜欢你啊 喜欢你 喜欢你啊 喜欢你 喜欢你啊 喜欢你 喜欢你啊 喜欢你 喜欢你啊 喜欢你 喜欢你啊 喜欢你 喜欢你啊 喜欢你 喜欢你啊 喜欢你 喜欢你啊 喜欢你 喜欢你啊 喜欢你 喜欢你啊 喜欢你 喜欢你啊 喜欢你 喜欢你啊 喜欢你 喜欢你啊 喜欢你 喜欢你啊 喜欢你 喜欢你啊 喜欢你 喜欢你啊 喜欢你 喜欢你啊 喜欢你 喜欢你啊 喜欢你 喜欢你啊 喜欢你 喜欢你啊 喜欢你 喜欢你啊 喜欢你 喜欢你啊 喜欢你 喜欢你啊 喜欢你 喜欢你啊 喜欢你 喜欢你啊 喜欢你 喜欢你啊 喜欢你 喜欢你啊 喜欢你 喜欢你啊 喜欢你 喜欢你啊 喜欢你 喜欢你啊 喜欢你 喜欢你啊 喜欢你 喜欢你啊 喜欢你 喜欢你啊 喜欢你 喜欢你啊 喜欢你 喜欢你啊 喜欢你 喜欢你啊 喜欢你 喜欢你啊 喜欢你 喜欢你啊 喜欢你 喜欢你啊 喜欢你 喜欢你啊 喜欢你 喜欢你啊 喜欢你 喜欢你啊 喜欢你 喜欢你啊 喜欢你 喜欢你啊 喜欢你 喜欢你啊 喜欢你 喜欢你啊 喜欢你 喜欢你啊 喜欢你 喜欢你啊 喜欢你 喜欢你啊 喜欢你 喜欢你啊 喜欢你 喜欢你啊 喜欢你 喜欢你啊 喜欢你 喜欢你啊 喜欢你 喜欢你啊 喜欢你 喜欢你啊 喜欢你 喜欢你啊 喜欢你 喜欢你啊 喜欢你 喜欢你啊 喜欢你 喜欢你啊 喜欢你 喜欢你啊 喜欢你 喜欢你啊 喜欢你 喜欢你啊 喜欢你 喜欢你啊 喜欢你 喜欢你啊 喜欢你 喜欢你啊 喜欢你 喜欢你啊 喜欢你 喜欢你啊 喜欢你 喜欢你啊 喜欢你 喜欢你啊 喜欢你 喜欢你啊 喜欢你 喜欢你啊 喜欢你 喜欢你啊 喜欢你 喜欢你啊 喜欢你 喜欢你啊 喜欢你 喜欢你啊 喜欢你 喜欢你啊 喜欢你 喜欢你啊 喜欢你 "
              font.pointSize: 14
              height: contentHeight
              width: frame.width - vbar.width
              y: -vbar.position * textEdit.height
              wrapMode: TextEdit.Wrap
              selectByKeyboard: true
              selectByMouse: true

              MouseArea{
                  anchors.fill: parent
                  /*鼠标/触摸板滚轮事件*/
                  onWheel: {
                      if (wheel.angleDelta.y > 0) //正值表示向上/向右旋转
                      {
                          vbar.decrease();
                      }
                      else {
                          vbar.increase();
                      }
                  }
                  onClicked: {
                      textEdit.forceActiveFocus();
                  }
              }
          }

          ScrollBar {
              id: vbar
              hoverEnabled: true
              active: hovered || pressed
              orientation: Qt.Vertical
              size: frame.height / textEdit.height
              width: 10
              anchors.top: parent.top
              anchors.right: parent.right
              anchors.bottom: parent.bottom
              position: 0
          }
          /*
          ScrollBar属性
          orientation 方向(水平/垂直Qt.Vertical)
          policy:控制滚动条显示【ScrollBar.AsNeeded/AlwaysOff/AlwaysOn】
          position: 0.5 //滚动条位置(0-1)
          size:滚动条大小(0-1)当前页高度/所有内容高度
          */
      }
}

 

 

目前参考资料:

https://blog.csdn.net/zhengtianzuo06/

你可能感兴趣的:(QT)