Flipable 是 Qt Quick 里一种可翻转的组件,一个物体有两面,配合旋转变换和动画,就能像扑克牌一样翻过去。这篇文章先用一张扑克牌展示它是如何翻转的,再把它应用到实际场景中展示如何切换设置、登录页面。
Flipable 翻转卡片
一张扑克牌,点击后绕竖轴翻转 180°,露出背面。

演示代码
qml
import QtQuick
import QtQuick.Layouts
FadeInAnimation {
ColumnLayout {
anchors.fill: parent
anchors.margins: 20
spacing: 15
// ... 省略标题组件 TitleSeparator ...
Flipable {
id: flipable
Layout.fillWidth: true
Layout.fillHeight: true
property bool flipped: false
front: Image {
anchors.fill: parent
source: "qrc:/images/SpadeA.png"
fillMode: Image.PreserveAspectFit
smooth: true
}
back: Image {
anchors.fill: parent
source: "qrc:/images/Background.png"
fillMode: Image.PreserveAspectFit
smooth: true
}
transform: Rotation {
id: rotation
origin.x: flipable.width / 2
origin.y: flipable.height / 2
axis.x: 0; axis.y: 1; axis.z: 0
angle: 0
}
states: State {
name: "back"
when: flipable.flipped
PropertyChanges { target: rotation; angle: 180 }
}
transitions: Transition {
NumberAnimation {
target: rotation
property: "angle"
duration: 600
easing.type: Easing.InOutQuad
}
}
MouseArea {
anchors.fill: parent
cursorShape: Qt.PointingHandCursor
onClicked: flipable.flipped = !flipable.flipped
}
}
Text {
text: "当前: " + (flipable.flipped ? "背面" : "正面")
font.pointSize: 10
color: "#666"
}
}
}
Flipable 做翻转,思路分四步:正反两面(front 和 back)先定义好,再使用 Rotation 用于旋转,用 states 声明翻到背面这个状态,最后由 transitions 把状态切换变成动画。
转动方向由 Rotation 的轴来决定,将轴设成竖轴就是扑克牌式的左右翻,改成横轴就变成上下翻。
还有个容易踩的小坑:旋转原点要放在组件中心,否则会绕着角落转,翻出来的效果是歪的。整套翻转说白了就是 状态变化 + 动画过渡。
适用场景:扑克牌、抽卡、正反面信息卡片。
Flipable 登录设置
登录界面和设置界面共用同一个 Flipable:

演示代码
qml
import QtQuick
import QtQuick.Controls
import QtQuick.Layouts
import "components"
FadeInAnimation {
ColumnLayout {
anchors.fill: parent
anchors.margins: 20
spacing: 15
// ... 省略标题组件 TitleSeparator ...
Flipable {
id: flipable
Layout.fillWidth: true
Layout.fillHeight: true
property bool flipped: false
front: Rectangle {
anchors.fill: parent
color: "#f8f9fa"
radius: 6
ColumnLayout {
anchors.fill: parent
anchors.margins: 16
spacing: 12
Text {
text: "用户登录"
font.pixelSize: 16
font.bold: true
color: "#333"
Layout.alignment: Qt.AlignHCenter
}
IconTextField {
id: usernameField
Layout.fillWidth: true
placeholderText: "请输入用户名"
iconSource: "qrc:/images/user-icon.png"
}
IconTextField {
id: passwordField
Layout.fillWidth: true
placeholderText: "请输入密码"
echoMode: TextField.Password
iconSource: "qrc:/images/lock-icon.png"
}
RowLayout {
Layout.fillWidth: true
Item { Layout.fillWidth: true }
Button {
text: "登录设置"
flat: true
font.pixelSize: 12
onClicked: flipable.flipped = true
}
}
PrimaryButton {
text: "登 录"
Layout.fillWidth: true
enabled: usernameField.text !== "" && passwordField.text !== ""
onClicked: console.log("登录:", usernameField.text)
}
}
}
back: Rectangle {
anchors.fill: parent
color: "#f8f9fa"
radius: 6
ColumnLayout {
anchors.fill: parent
anchors.margins: 16
spacing: 12
Text {
text: "登录设置"
font.pixelSize: 16
font.bold: true
color: "#333"
Layout.alignment: Qt.AlignHCenter
}
CheckBox {
text: "记住密码"
Layout.fillWidth: true
}
CheckBox {
text: "自动登录"
Layout.fillWidth: true
}
CheckBox {
text: "启用指纹登录"
Layout.fillWidth: true
}
Item { Layout.fillHeight: true }
PrimaryButton {
text: "保存并返回"
Layout.fillWidth: true
onClicked: flipable.flipped = false
}
}
}
transform: Rotation {
id: rotation
origin.x: flipable.width / 2
origin.y: flipable.height / 2
axis.x: 0; axis.y: 1; axis.z: 0
angle: 0
}
states: State {
name: "back"
when: flipable.flipped
PropertyChanges { target: rotation; angle: 180 }
}
transitions: Transition {
NumberAnimation {
target: rotation
property: "angle"
duration: 600
easing.type: Easing.InOutQuad
}
}
}
}
}
这个 demo 把翻转效果应用到了实际的场景中,front 是登录表单,用户名、密码、登录按钮齐全;back 是设置页。
点击按钮(登录设置),代码将 flipped 设置为 true 并翻到设置页,点击按钮(保存并返回)置回 false 翻回来,翻转动画和刚才的demo一样。
适用场景:登录/设置切换、引导页翻页、同区域双界面的轻量切换。
已验证环境:
- Qt 版本:Qt 6.8.2、Qt 6.11.1
- 操作系统:Windows 11
- GitHub:QML-Minimal-Demos/qml_flickable_flipable