前言
最近在学习qml,发现了一个很好用的库FluentUI,这个库是一个基于qml的Fluent Design风格的UI库,可以实现一些美观的界面。在这里记录一些我学习过程中写的一些小例子。
例子
悬停变色的网格
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63
| import QtQuick 2.15 import QtQuick.Window 2.15 import QtQuick.Controls 2.15 import QtQuick.Layouts 1.15 import FluentUI 1.0
FluWindow { id: window property int row: 20 property int column: 20 property var colors: ['#e74c3c', '#8e44ad', '#3498db', '#e67e22', '#2ecc71']
Grid { anchors.centerIn: parent rows: window.row columns: window.column spacing: 5 Repeater { model: window.row * window.column FluRectangle{ id: rect width: height height: window.height / window.row / 2 color: "#fff"
MouseArea { id: mouseArea anchors.fill: parent hoverEnabled: true onEntered: { colorAnimation.stop() rect.color = window.get_random_color() } onExited: { colorAnimation.start() } }
ColorAnimation { id: colorAnimation target: rect property: "color" to: "#fff" duration: 1000 running: false } } } }
function get_random_color() { return colors[Math.floor(Math.random() * 5)] } }
|
渐变背景
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60
| import QtQuick 2.15 import QtQuick.Window 2.15 import QtQuick.Controls 2.15 import QtQuick.Layouts 1.15 import FluentUI 1.0
FluWindow { FluFrame { id: window width: parent.width * 0.8 height: parent.height * 0.8 anchors.centerIn: parent clip: true FluText { text: "这是一个不停变换的渐变背景" anchors.centerIn: parent font: FluTextStyle.Title z: 1 }
Item { id: gradientArea width: window.width height: window.height * 2 clip: true
Rectangle { anchors.fill: parent gradient: Gradient { GradientStop { position: 0.00; color: "#27ae60" } GradientStop { position: 0.25; color: "#2980b9" } GradientStop { position: 0.50; color: "#8e44ad" } GradientStop { position: 0.75; color: "#f794a4" } GradientStop { position: 1.00; color: "#f5576c" } } }
SequentialAnimation { running: true loops: Animation.Infinite
NumberAnimation { target: gradientArea property: "y" from: -(gradientArea.height - window.height) to: 0 duration: 10000 }
NumberAnimation { target: gradientArea property: "y" from: 0 to: -(gradientArea.height - window.height) duration: 10000 } } } } }
|
不偷看密码的猫头鹰
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166
| import QtQuick 2.15 import QtQuick.Window 2.15 import QtQuick.Controls 2.15 import QtQuick.Layouts 1.15 import FluentUI 1.0
FluWindow{ title: "不偷看密码的猫头鹰"
Rectangle { id: window anchors.fill: parent state: "noInput" gradient: Gradient { GradientStop { position: 0.00; color: "#4facfe" } GradientStop { position: 1.00; color: "#00f2fe" } }
FluRectangle { id: owlHandLeft z: 3 color: "#472d20" width: 34 height: 34 radius: [17, 17, 17, 17] transform: [Scale{ yScale: 0.6 }, Translate{ x: (window.width - owlArmLeft.width) / 2 - 80; y: (window.height - owlArmLeft.height) / 2 - 30}] }
FluImage { id: owlArmLeft z: 2 source: "qrc:/res/owl-login-arm.png" fillMode: Image.PreserveAspectCrop transform: [Translate{ x: (window.width - owlArmLeft.width) / 2 - 80; y: (window.height - owlArmLeft.height) / 2 - 25}] }
FluImage { id: owlHead anchors.centerIn: parent source: "qrc:/res/owl-login.png" transform: [Translate{y: -90}] }
FluImage { id: owlArmRight z: 2 source: "qrc:/res/owl-login-arm.png" fillMode: Image.PreserveAspectCrop transform: [Scale{ xScale: -1 }, Translate{ x: (window.width - owlArmLeft.width) / 2 + owlArmLeft.width + 80; y: (window.height - owlArmLeft.height) / 2 - 25}] }
FluRectangle { id: owlHandRight z: 3 color: "#472d20" width: 34 height: 34 radius: [17, 17, 17, 17] transform: [Scale{ yScale: 0.6 }, Translate{ x: (window.width - owlArmLeft.width) / 2 + 80; y: (window.height - owlArmLeft.height) / 2 - 30}] }
Column { id: content z: 2 spacing: 10 anchors.top: owlHead.bottom anchors.horizontalCenter: parent.horizontalCenter anchors.centerIn: parent anchors.topMargin: height / 2 - 5 - spacing
FluTextBox { id: name padding: 10 placeholderText: "请输入用户名" }
FluTextBox { id: password padding: 10 placeholderText: "请输入密码" echoMode: TextInput.Password onFocusChanged: { window.state = window.state === "noInput" ? "input" : "noInput" } } }
Column { id: buttons spacing: 10 anchors.top: content.bottom anchors.horizontalCenter: parent.horizontalCenter anchors.topMargin: 20
FluFilledButton { width: 100 text: "登录" onClicked: { } }
FluButton { width: 100 text: "注册" onClicked: { } } }
transitions: [ Transition { NumberAnimation { targets: [owlHandLeft, owlHandRight] properties: "x, y, scale, z" duration: 300 } NumberAnimation { targets: [owlArmLeft, owlArmRight] properties: "x, y, scale, z" duration: 300 } } ]
states: [ State { name: "noInput" PropertyChanges { target: owlHandLeft x: 0; y: 0; scale: 1; z: 3 } PropertyChanges { target: owlHandRight x: 0; y: 0; scale: 1; z: 3 } PropertyChanges { target: owlArmLeft x: 0; y: 0 } PropertyChanges { target: owlArmRight x: 0; y: 0 } }, State { name: "input" PropertyChanges { target: owlHandLeft x: 46; y: -20; scale: 0.6; z: 1 } PropertyChanges { target: owlHandRight x: -46; y: -20; scale: 0.6; z: 1 } PropertyChanges { target: owlArmLeft x: 50; y: -35 } PropertyChanges { target: owlArmRight x: -50; y: -35 } } ] } }
|
跟随鼠标的纸飞机
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60
| import QtQuick 2.15 import QtQuick.Window 2.15 import QtQuick.Controls 2.15 import QtQuick.Layouts 1.15 import FluentUI 1.0
FluWindow { id: window title: "始终飞向鼠标的纸飞机"
Rectangle { anchors.fill: parent gradient: Gradient { GradientStop { position: 0.00; color: "#d4fc79" } GradientStop { position: 1.00; color: "#96e6a1" } } }
FluImage { id: plane width: 70 height: 70 source: "qrc:/res/plane.svg" }
ParallelAnimation { id: moveAnimation PropertyAnimation { target: plane property: "x" to: mouseArea.mouseX - plane.width / 2 duration: 100 easing.type: Easing.Linear } PropertyAnimation { target: plane property: "y" to: mouseArea.mouseY - plane.height / 2 duration: 100 easing.type: Easing.Linear } }
MouseArea { id: mouseArea anchors.fill: parent hoverEnabled: true
onPositionChanged: { var targetX = mouseX - plane.width / 2; var targetY = mouseY - plane.height / 2; var dx = targetX - plane.x; var dy = targetY - plane.y; plane.rotation = Math.atan2(dy, dx) * 180 / Math.PI + 45; if (!moveAnimation.running) { moveAnimation.start(); } } } }
|
滚动特效
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47
| import QtQuick 2.15 import QtQuick.Window 2.15 import QtQuick.Controls 2.15 import QtQuick.Layouts 1.15 import FluentUI 1.0
FluWindow { id: window title: "滚动特效" property var colors: ['#e74c3c', '#8e44ad', '#3498db', '#e67e22', '#2ecc71']
Flickable { id:flickview clip: true anchors.fill: parent contentWidth: parent.width contentHeight: column.height ScrollBar.vertical: FluScrollBar {}
Column { id: column anchors.horizontalCenter: parent.horizontalCenter spacing: 20
Repeater { model: 40 delegate: FluRectangle { property bool below: flickview.contentY + window.height < y
width: flickview.width - 200 height: 200 color: get_random_color() y: index * (height + column.spacing) scale: below ? 0 : 1 opacity: below ? 0 : 1
Behavior on scale { NumberAnimation { duration: 500 } } Behavior on opacity { NumberAnimation { duration: 500 } } } } } }
function get_random_color() { return colors[Math.floor(Math.random() * 5)] } }
|
波浪小球
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46
| import QtQuick 2.15 import QtQuick.Window 2.15 import QtQuick.Controls 2.15 import QtQuick.Layouts 1.15 import FluentUI 1.0
FluWindow { title: "水波效果"
ColumnLayout { anchors.centerIn: parent spacing: 50 FluClip { width: 200 height: 200 radius: [100, 100, 100, 100] color: "#333" FluRectangle { id: waterBall width: 800 height: 800 radius: [300, 300, 300, 300] color: "#0078D4" anchors.horizontalCenter: parent.horizontalCenter y: 240 - slider.value * 2.4
RotationAnimation { loops: Animation.Infinite running: true target: waterBall from: 0 to: 360 duration: 5000 } } }
FluSlider { id: slider Layout.alignment: Qt.AlignHCenter from: 0 to: 100 stepSize: 1 } } }
|