前言
书接上文,这篇文章讲的是如何实现将日程安排按标签分类并显示,且标签可由用户自定义。
实现思路
- 在数据库中创建一个labels表格,里面记录标签名字数据。
(注:原有的tasks表记录和日程安排有关的信息)
- ui界面显示labels表的查询结果,如果手动输入的字段已存在,则不写入数据库,否则,ui界面的model中添加且写入数据库
(注:写入数据库是永久的,但是ui的model是动态加载的,标签列表是组件加载完成时就已经读取的,新添加了某个字段后并不会重新读取数据库中的信息并更新数据,所以需要通过手动加入到ui的model中,但是下一次重新打开并加载应用时该条记录是源于读数据库,而之前对model的操作已经失效,保证了在用户层面只会看到标签被添加后立即生效且之后也不失效)
- 在待办事项表格中新增label列,每次查询数据时用label作为tasks表的查询条件
实现方案
使用ComboBox展示标签列表
基础知识
关于ComboBox
ComboBox是Qt中自带的一个组件,在界面上体现为一个单选的下拉框。其基本形式如下:
qml
ComboBox {
id:xxx
model: ["First", "Second", "Third"]
}
其中model里的就是它要展示的数据,数据类型可以是多种,像这样的字符串、Integer、ListModel、js形式的数组等等都可以。
还有一些常用属性,比如editable: editable: true
如果想要实现新增标签功能则可以在qml写入如下js代码(非ui.qml文件中!)
qml
id.onAccepted: {
if (find(editText) === -1)
model.append({text: editText})
}
其中id是ComboBox定义的id值。
而对于复杂一些的元素类型,比如ListModel中的ListElement,例如:
qml
ListModel {
id: fruitModel
ListElement {
name: "Apple"
cost: 2.45
}
}
则要注意,name和cost等是该元素的一个属性,后续展示某个属性值的时候,对应属性的名称一定不要写错或者混用,否则就无法显示数据。
关于同一项目下一个A.qml调用B.qml文件定义的组件及其属性
步骤:
- 在A.ui.qml代码中实例化B.qml
css
//A.ui.qml中的代码
B{
id:b
}
- 假设B有一个函数是func(),在A.qml代码的方法中可以直接调用:
b.func()
Qt中的界面展示与后台交互逻辑
交互逻辑三要素:data Model View
其中,data被添加到Model中,而Model则展示在View中。
而在本例中,ComboBox起到了一个View的作用,所以可以直接使用。如果是自定义一个列表来展示,比如示例代码中的事项列表,则需要专门的TaskListView.qml
和TaskListViewForm.ui.qml
文件。
具体实现步骤
- 创建labels表
qml
tx.executeSql('CREATE TABLE IF NOT EXISTS labels(
label_id INTEGER PRIMARY KEY AUTOINCREMENT,
labelname TEXT
)');
- 编写数据库查询接口
qml
function getLabels() {
let labels = []
console.log("start read data from table labels")
root._database().transaction(function(tx){
let results = tx.executeSql("SELECT labelname FROM labels")
for (let i = 0; i < results.rows.length; i++) {
let row = results.rows.item(i)
labels.push({"text":row.labelname})
}
})
return labels;
}
- 在ui.qml文件中新建一个ComboBox:
qml
property alias labelSelectModel:labelSelect.model
...
ComboBox {
id: labelSelect
editable: true
model: ListModel {
id: model
ListElement { text: "工作" }
ListElement { text: "生日" }
}
}
- 添加数据至model中
qml
function createLabelLists() : void {
var labels = Database.getLabels()
labels.forEach(function(label){
labelSelectModel.append(label);
})
}