参考网上一些QML效果的小例子在此做下记录,代码大多由网路各大神提供,自己编译运行,从中对自己不知道的部分,查阅资料后,添加注释,积累经验,望提高。
持续更新...
目录
1.BusyIndicator [等待指示器]
2.任意选择表情
3.图片切成任意形状显示
4.侧边栏平移滑动动画效果
5.模拟微信页面滑动栏
6.侧边滚动条
代码
//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
}
}
}
实现方法: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"})
}
}
}
原图
效果图
实现: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
}
}
}
效果
实现方法:使用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;
}
}
实现方式
上部分使用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更新
实现:使用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/