目录
一,查看官方第一个示例(alarm)源代码
Qt 快速应用程序向导创建一个包含以下源文件的项目:
源文件 | 目的 |
---|---|
alarms.pro | 项目文件 |
main.cpp | 应用程序的主C++代码文件。 |
qml.qrc | 资源文件,其中包含源文件的名称(main.cpp和项目文件除外)。 |
alarms.pro
QT += quick
CONFIG += c++11
# The following define makes your compiler emit warnings if you use
# any Qt feature that has been marked deprecated (the exact warnings
# depend on your compiler). Refer to the documentation for the
# deprecated API to know how to port your code away from it.
DEFINES += QT_DEPRECATED_WARNINGS
# You can also make your code fail to compile if it uses deprecated APIs.
# In order to do so, uncomment the following line.
# You can also select to disable deprecated APIs only up to a certain version of Qt.
#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0
SOURCES += \
main.cpp
RESOURCES += qml.qrc
# Additional import path used to resolve QML modules in Qt Creator's code model
QML_IMPORT_PATH =
# Additional import path used to resolve QML modules just for Qt Quick Designer
QML_DESIGNER_IMPORT_PATH =
# Default rules for deployment.
qnx: target.path = /tmp/$${TARGET}/bin
else: unix:!android: target.path = /opt/$${TARGET}/bin
!isEmpty(target.path): INSTALLS += target
main.cpp
#include <QGuiApplication>
#include <QQmlApplicationEngine>
int main(int argc, char *argv[])
{
QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
QGuiApplication app(argc, argv);
QQmlApplicationEngine engine;
engine.load(QUrl(QStringLiteral("qrc:/main.qml")));
if (engine.rootObjects().isEmpty())
return -1;
return app.exec();
}
其他源文件(qml.qrc/)
源文件 | 目的 |
---|---|
qtquickcontrols2.conf | 选择具有深色主题的材质样式。 |
main.qml | 链接AlarmDialog.qml, AlarmModel.qml, AlarmDelegate.qml ,TumblerDelegate.qml |
AlarmDialog.qml | 定义用于添加新闹钟的对话框。 |
AlarmDelegate.qml | 定义应用主屏幕的布局。 |
AlarmModel.qml | 定义用于存储警报数据的列表模型。 |
TumblerDelegate.qml | 定义滚筒的图形布局 |
AlarmDelegate.qml
主屏幕中的每个报警都是一个ItemDelegate。ItemDelegate根目录包含主屏幕和详细屏幕上的所有字段。详细信息屏幕的字段仅在单击报警后可见,即 root.checked=true。
import QtQuick 2.11
import QtQuick.Controls 2.4
import QtQuick.Controls.Material 2.4
import QtQuick.Layouts 1.11
import QtQuick.Window 2.11
ItemDelegate {
id: root
width: parent.width
checkable: true
onClicked: ListView.view.currentIndex = index
contentItem: ColumnLayout {
spacing: 0
RowLayout {
ColumnLayout {
id: dateColumn
readonly property date alarmDate: new Date(
model.year, model.month - 1, model.day, model.hour, model.minute)
Label {
id: timeLabel
font.pixelSize: Qt.application.font.pixelSize * 2
text: dateColumn.alarmDate.toLocaleTimeString(window.locale, Locale.ShortFormat)
}
RowLayout {
Label {
id: dateLabel
text: dateColumn.alarmDate.toLocaleDateString(window.locale, Locale.ShortFormat)
}
Label {
id: alarmAbout
text: "⸱ " + model.label
visible: model.label.length > 0 && !root.checked
}
}
}
Item {
Layout.fillWidth: true
}
Switch {
checked: model.activated
Layout.alignment: Qt.AlignTop
onClicked: model.activated = checked
}
}
CheckBox {
id: alarmRepeat
text: qsTr("Repeat")
checked: model.repeat
visible: root.checked
onToggled: model.repeat = checked
}
Flow {
visible: root.checked && model.repeat
Layout.fillWidth: true
Repeater {
id: dayRepeater
model: daysToRepeat
delegate: RoundButton {
text: Qt.locale().dayName(model.dayOfWeek, Locale.NarrowFormat)
flat: true
checked: model.repeat
checkable: true
Material.background: checked ? Material.accent : "transparent"
onToggled: model.repeat = checked
}
}
}
TextField {
id: alarmDescriptionTextField
placeholderText: qsTr("Enter description here")
cursorVisible: true
visible: root.checked
text: model.label
onTextEdited: model.label = text
}
Button {
id: deleteAlarmButton
text: qsTr("Delete")
width: 40
height: 40
visible: root.checked
onClicked: root.ListView.view.model.remove(root.ListView.view.currentIndex, 1)
}
}
}
AlarmDialog.qml
此对话框屏幕有一个行布局(RowLayout),每个行布局有一个用于小时和分钟的Tumbler,另一个行布局有一个用于日、月和年的Tumbler。
如果您单击对话中的"确定",输入的数据将被添加到:alarmModel
import QtQuick 2.11
import QtQuick.Controls 2.4
import QtQuick.Layouts 1.11
import QtQuick.Window 2.11
Dialog {
id: alarmDialog
title: "Add new alarm"
modal: true
standardButtons: DialogButtonBox.Ok | DialogButtonBox.Cancel
property AlarmModel alarmModel
function formatNumber(number) {
return number < 10 && number >= 0 ? "0" + number : number.toString()
}
onAccepted: {
alarmModel.append({
"hour": hoursTumbler.currentIndex,
"minute": minutesTumbler.currentIndex,
"day": dayTumbler.currentIndex + 1,
"month": monthTumbler.currentIndex + 1,
"year": yearTumbler.years[yearTumbler.currentIndex],
"activated": true,
"label": "",
"repeat": false,
"daysToRepeat": [
{ "dayOfWeek": 0, "repeat": false },
{ "dayOfWeek": 1, "repeat": false },
{ "dayOfWeek": 2, "repeat": false },
{ "dayOfWeek": 3, "repeat": false },
{ "dayOfWeek": 4, "repeat": false },
{ "dayOfWeek": 5, "repeat": false },
{ "dayOfWeek": 6, "repeat": false }
],
})
}
onRejected: alarmDialog.close()
contentItem: RowLayout {
RowLayout {
id: rowTumbler
Tumbler {
id: hoursTumbler
model: 24
delegate: TumblerDelegate {
text: formatNumber(modelData)
}
}
Tumbler {
id: minutesTumbler
model: 60
delegate: TumblerDelegate {
text: formatNumber(modelData)
}
}
}
RowLayout {
id: datePicker
Layout.leftMargin: 20
property alias dayTumbler: dayTumbler
property alias monthTumbler: monthTumbler
property alias yearTumbler: yearTumbler
readonly property var days: [31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]
Tumbler {
id: dayTumbler
function updateModel() {
// Populate the model with days of the month. For example: [0, ..., 30]
var previousIndex = dayTumbler.currentIndex
var array = []
var newDays = datePicker.days[monthTumbler.currentIndex]
for (var i = 1; i <= newDays; ++i)
array.push(i)
dayTumbler.model = array
dayTumbler.currentIndex = Math.min(newDays - 1, previousIndex)
}
Component.onCompleted: updateModel()
delegate: TumblerDelegate {
text: formatNumber(modelData)
}
}
Tumbler {
id: monthTumbler
onCurrentIndexChanged: dayTumbler.updateModel()
model: 12
delegate: TumblerDelegate {
text: window.locale.standaloneMonthName(modelData, Locale.ShortFormat)
}
}
Tumbler {
id: yearTumbler
// This array is populated with the next three years. For example: [2018, 2019, 2020]
readonly property var years: (function() {
var currentYear = new Date().getFullYear()
return [0, 1, 2].map(function(value) { return value + currentYear; })
})()
model: years
delegate: TumblerDelegate {
text: formatNumber(modelData)
}
}
}
}
}
AlarmModel.qml
此QML文件包含alarmModel的定义,alarmModel是管理报警数据的 ListModel 。
它创建了五个列表元素和示例警报。
import QtQuick 2.11
// Populate the model with some sample data.
ListModel {
id: alarmModel
ListElement {
hour: 6
minute: 0
day: 2
month: 8
year: 2018
activated: true
label: "Wake up"
repeat: true
daysToRepeat: [
ListElement { dayOfWeek: 0; repeat: false },
ListElement { dayOfWeek: 1; repeat: false },
ListElement { dayOfWeek: 2; repeat: false },
ListElement { dayOfWeek: 3; repeat: false },
ListElement { dayOfWeek: 4; repeat: false },
ListElement { dayOfWeek: 5; repeat: false },
ListElement { dayOfWeek: 6; repeat: false }
]
}
ListElement {
hour: 6
minute: 0
day: 3
month: 8
year: 2018
activated: true
label: "Wake up"
repeat: true
daysToRepeat: [
ListElement { dayOfWeek: 0; repeat: true },
ListElement { dayOfWeek: 1; repeat: true },
ListElement { dayOfWeek: 2; repeat: true },
ListElement { dayOfWeek: 3; repeat: true },
ListElement { dayOfWeek: 4; repeat: true },
ListElement { dayOfWeek: 5; repeat: false },
ListElement { dayOfWeek: 6; repeat: false }
]
}
ListElement {
hour: 7
minute: 0
day: 3
month: 8
year: 2018
activated: false
label: "Exercise"
repeat: true
daysToRepeat: [
ListElement { dayOfWeek: 0; repeat: true },
ListElement { dayOfWeek: 1; repeat: true },
ListElement { dayOfWeek: 2; repeat: true },
ListElement { dayOfWeek: 3; repeat: true },
ListElement { dayOfWeek: 4; repeat: true },
ListElement { dayOfWeek: 5; repeat: true },
ListElement { dayOfWeek: 6; repeat: true }
]
}
ListElement {
hour: 5
minute: 15
day: 1
month: 9
year: 2018
activated: true
label: ""
repeat: false
daysToRepeat: [
ListElement { dayOfWeek: 0; repeat: false },
ListElement { dayOfWeek: 1; repeat: false },
ListElement { dayOfWeek: 2; repeat: false },
ListElement { dayOfWeek: 3; repeat: false },
ListElement { dayOfWeek: 4; repeat: false },
ListElement { dayOfWeek: 5; repeat: false },
ListElement { dayOfWeek: 6; repeat: false }
]
}
ListElement {
hour: 5
minute: 45
day: 3
month: 9
year: 2018
activated: false
label: ""
repeat: false
daysToRepeat: [
ListElement { dayOfWeek: 0; repeat: false },
ListElement { dayOfWeek: 1; repeat: false },
ListElement { dayOfWeek: 2; repeat: false },
ListElement { dayOfWeek: 3; repeat: false },
ListElement { dayOfWeek: 4; repeat: false },
ListElement { dayOfWeek: 5; repeat: false },
ListElement { dayOfWeek: 6; repeat: false }
]
}
}
main.qml
主窗口是
ApplicationWindow QML类型,是此应用程序中的根项。
ListView alarmListView将alarmModel中的数据与alarmDelegate中定义的布局相结合。
可以通过单击 RoundButton添加新的闹钟。单击它将打开一个对话框屏幕alarmDialog。
import QtQuick 2.11
import QtQuick.Controls 2.4
import QtQuick.Controls.Material 2.4
import QtQuick.Layouts 1.11
import QtQuick.Window 2.11
import Qt.labs.calendar 1.0
ApplicationWindow {
id: window
width: 400
height: 500
visible: true
ListView {
id: alarmListView
anchors.fill: parent
model: AlarmModel {}
delegate: AlarmDelegate {}
}
RoundButton {
id: addAlarmButton
text: "+"
anchors.bottom: alarmListView.bottom
anchors.bottomMargin: 8
anchors.horizontalCenter: parent.horizontalCenter
onClicked: alarmDialog.open()
}
AlarmDialog {
id: alarmDialog
x: Math.round((parent.width - width) / 2)
y: Math.round((parent.height - height) / 2)
alarmModel: alarmListView.model
}
}
TumblerDelegate.qml
TumblerDelegate定义了Tumblers的图形属性。
import QtQuick 2.11
import QtQuick.Controls 2.4
import QtQuick.Controls.Material 2.4
Text {
text: modelData
color: Tumbler.tumbler.Material.foreground
font: Tumbler.tumbler.font
opacity: 1.0 - Math.abs(Tumbler.displacement) / (Tumbler.tumbler.visibleItemCount / 2)
horizontalAlignment: Text.AlignHCenter
verticalAlignment: Text.AlignVCenter
}
二,编译并在Ubuntu运行
三,思考题
添加了暗主题