一、前言
上次了解了使用qml实现常见的一些控件,在设备上也做了测试,基本的简单页面已经可以开发出来了,但是实际使用中都是多个页面的,多个页面的切换也是必不可少的,这一次我们就再问一下trae如何进行qml的多页面开发,而且多个页面我们也通过多个qml文件来区分,保证可复用性。
二、qml常见页面切换方式
直接问trae:

在你的项目中,我建议使用 StackView 方式,因为它:
- 有完整的页面栈管理
- 支持前进/后退动画
- 内存管理更高效
- 与你的现有项目结构兼容性好
需要特别注意:
- 每个页面最好封装为单独的 Component 或 QML 文件
- 页面切换时要处理好数据传递
- 安卓/iOS 上有原生风格的过渡动画可用
在 QML 中,常见的页面切换方式有以下几种,我将结合你的当前项目结构为你详细介绍:
1. 使用 StackView(推荐方式)
StackView 是最常用的页面管理组件,适合大多数应用场景。
plain
import QtQuick 2.12
import QtQuick.Window 2.12
import QtQuick.Controls 2.12
Window {
// ... existing code ...
StackView {
id: stackView
anchors.fill: parent
initialItem: Page1 {}
}
Component {
id: page1
Rectangle {
color: "lightblue"
Button {
text: "去第二页"
onClicked: stackView.push(page2)
}
}
}
Component {
id: page2
Rectangle {
color: "lightgreen"
Button {
text: "返回"
onClicked: stackView.pop()
}
}
}
}
测试代码:
我们创建包括main.qml的三个qml文件:main.qml、home.qml、login.qml,main.qml用于控制切换,login.qml设计为登录页面,home.qml为进入后的主页,默认显示登录页面,点击登录按钮后进入home页面,点击home页面的返回则退出到登录页面。
javascript
import QtQuick 2.12
import QtQuick.Window 2.12
import QtQuick.Controls 2.12
Window {
width: 720
height: 1440
visible: true
title: qsTr("登录应用")
StackView {
id: stackView
anchors.fill: parent
initialItem: Qt.createComponent("login.qml").createObject(stackView, {"stackView": stackView})
}
}
javascript
import QtQuick 2.12
import QtQuick.Controls 2.12
Rectangle {
id: loginPage
property var stackView
width: parent.width
height: parent.height
Column {
anchors.centerIn: parent
spacing: 20
Label {
text: "登录页面"
font.pixelSize: 24
}
Button {
text: "登录"
onClicked: stackView.push(Qt.resolvedUrl("home.qml"), {"stackView": stackView})
}
}
}
javascript
import QtQuick 2.12
import QtQuick.Controls 2.12
Rectangle {
id: homePage
property var stackView
width: parent.width
height: parent.height
color: "lightgreen"
Column {
anchors.centerIn: parent
spacing: 20
Label {
text: "欢迎来到主页"
font.pixelSize: 24
}
Button {
text: "返回登录页"
onClicked: stackView.pop()
}
}
}
测试效果:

2. 使用 Loader 动态加载
适合需要频繁切换但不需要保留页面状态的场景。
plain
// ... existing code ...
Loader {
id: pageLoader
anchors.fill: parent
sourceComponent: page1
}
Button {
text: "切换页面"
onClicked: pageLoader.sourceComponent =
(pageLoader.sourceComponent == page1) ? page2 : page1
}
// ... existing code ...
测试代码:
也是三个qml文件,这种方式感觉简单很多,但是没有切换页面的效果:
javascript
import QtQuick 2.12
import QtQuick.Controls 2.12
Window {
width: 720
height: 1440
visible: true
title: qsTr("Loader示例")
property string currentPage: "login.qml"
Loader {
id: pageLoader
anchors.fill: parent
source: currentPage
}
Connections {
target: pageLoader.item
ignoreUnknownSignals: true
function onChangePage(page) {
currentPage = page
}
}
}
javascript
import QtQuick 2.12
import QtQuick.Controls 2.12
Item {
signal changePage(string page)
Column {
anchors.centerIn: parent
spacing: 20
Label {
text: "登录页面"
font.pixelSize: 24
}
Button {
text: "登录"
onClicked: changePage("home.qml")
}
}
}
javascript
import QtQuick 2.12
import QtQuick.Controls 2.12
Item {
signal changePage(string page)
Column {
anchors.centerIn: parent
spacing: 20
Label {
text: "欢迎来到主页"
font.pixelSize: 24
}
Button {
text: "返回登录页"
onClicked: changePage("login.qml")
}
}
}
测试效果:

3. 使用 SwipeView
适合需要左右滑动切换页面的场景。
plain
// ... existing code ...
import QtQuick.Controls 2.12
SwipeView {
id: swipeView
anchors.fill: parent
Page1 {}
Page2 {}
Page3 {}
}
PageIndicator {
anchors.bottom: parent.bottom
currentIndex: swipeView.currentIndex
count: swipeView.count
}
// ... existing code ...
测试代码:
这种也是三个文件,用户左右滑动进行页面切换,很多app都是这种切换方式:
javascript
import QtQuick 2.12
import QtQuick.Window 2.12
import QtQuick.Controls 2.12
Window {
width: 720
height: 1440
visible: true
title: qsTr("滑动视图示例")
SwipeView {
id: swipeView
anchors.fill: parent
currentIndex: 0
interactive: true
Loader {
source: "login.qml"
}
Loader {
source: "home.qml"
}
}
PageIndicator {
anchors.bottom: parent.bottom
anchors.horizontalCenter: parent.horizontalCenter
count: swipeView.count
currentIndex: swipeView.currentIndex
}
}
javascript
import QtQuick 2.12
import QtQuick.Controls 2.12
Rectangle {
width: parent.width
height: parent.height
Column {
anchors.centerIn: parent
spacing: 20
Label {
text: "登录页面"
font.pixelSize: 24
}
Button {
text: "滑动到主页"
onClicked: swipeView.currentIndex = 1
}
}
}
javascript
import QtQuick 2.12
import QtQuick.Controls 2.12
Rectangle {
width: parent.width
height: parent.height
Column {
anchors.centerIn: parent
spacing: 20
Label {
text: "欢迎来到主页"
font.pixelSize: 24
}
Button {
text: "滑动回登录页"
onClicked: swipeView.currentIndex = 0
}
}
}
测试效果:

4. 使用 TabBar + StackLayout
适合需要标签页导航的场景。
plain
// ... existing code ...
TabBar {
id: tabBar
TabButton { text: "首页" }
TabButton { text: "设置" }
}
StackLayout {
currentIndex: tabBar.currentIndex
Page1 {}
Page2 {}
}
// ... existing code ...
测试代码:
也是分为三个页面,这种方式也是用的比较多的:
javascript
import QtQuick 2.12
import QtQuick.Window 2.12
import QtQuick.Controls 2.12
import QtQuick.Layouts 1.12
Window {
width: 720
height: 1440
visible: true
title: qsTr("底部标签栏示例")
// 主布局容器
Column {
anchors.fill: parent
StackLayout {
id: stackLayout
width: parent.width
height: parent.height - tabBar.height
currentIndex: tabBar.currentIndex
// 登录页面
Loader {
source: "login.qml"
}
// 主页
Loader {
source: "home.qml"
}
}
// 底部标签栏
TabBar {
id: tabBar
width: parent.width
position: TabBar.Footer
currentIndex: 0
TabButton {
text: qsTr("登录")
}
TabButton {
text: qsTr("主页")
}
}
}
}
javascript
import QtQuick 2.12
import QtQuick.Controls 2.12
Item {
width: parent.width
height: parent.height
Column {
anchors.centerIn: parent
spacing: 20
Label {
text: "登录页面"
font.pixelSize: 24
}
Button {
text: "滑动到主页"
onClicked: swipeView.currentIndex = 1
}
}
}
javascript
import QtQuick 2.12
import QtQuick.Controls 2.12
Item {
width: parent.width
height: parent.height
Column {
anchors.centerIn: parent
spacing: 20
Label {
text: "欢迎来到主页"
font.pixelSize: 24
}
Button {
text: "滑动回登录页"
onClicked: swipeView.currentIndex = 0
}
}
}
测试效果:

三、最后
这些页面切换方式其实没有绝对的好坏,主要还是要分场景去使用的。