TableView 就是 Qt Quick 为表格式呈现数据提供的组件。想必兄台用过 Excel,可以藉此想象下 TableView 的效果。
TableView 与 ListView 类似,相比之下多了滚动条、挑选、可调整尺寸的表头等特性。 它的数据也通过 Model 来提供,你可以使用 ListModel、XmlListModel,也可以使用 C++ 中从 QAbstractltemModel、QAbstractTableModel 等继承而实现的 Model。
使用 ListView 也可以将数据呈现为表格样式,不过稍微有些复杂,尤其是 delegate 的定义,当数据有很多列(比如播放列表、进销存管理、学生成绩表等)时,就会很复杂,再要有排序之类的操作,那就……此时就是 TableView 的用武之地了。
一、—个简单的TableView实例
下面是前面讲 ListView 时的示例,采用 TableView 来重写一下。QML 文件 phone_table_ simple.qml 的内容如下:
import QtQuick 2.0
import QtQuick.Window 2.3
import QtQuick.Controls 1.2
Window {
width: 360
height: 360
visible: true
TableView{
id: phoneTable
anchors.fill: parent
focus: true
// TableViewColumn 描述表格的每一列
TableViewColumn{role: "name"; title: "Name"; width: 80; elideMode: Text.ElideRight;}
TableViewColumn{role: "cost"; title: "Cost"; width: 100;}
TableViewColumn{role: "manufacture"; title: "Manufacture"; width: 140;}
model: ListModel{
id: phoneModel
ListElement{
name: "rongyao2";
cost: "4900";
manufacture: "huawei"
}
ListElement{
name: "s6";
cost: "4800";
manufacture :"sumsung"
}
ListElement{
name: "apple5"
cost: "3300"
manufacture: "apple"
}
ListElement{
name: "Mi5"
cost: "3200"
manufacture: "xiaomi"
}
} // model is end
}
}
效果如下图所示:
二、TableViewColumn 属性讲解
定义了 TableViewColumn,描述表格的每一列,这是必需的,否则表格无法显示。示例中用到 role、title、width 三个属性,这是要使用 TableViewColumn 的最小属性集,role 对应 Model 中 ListElement 中的 role-name,正是这个属性完成了二维表格与一维 Model 之间的数据映射;title 是表头中一列的标题;width 定义列宽。
role、title、width
这三个属性,是要使用 TableViewColumn 的最小属性集,role 对应 Model 中 ListElement 中的 role-name,正是这个属性完成了二维表格与一维 Model 之间的数据映射;title 是表头中一列的标题;width 定义列宽;
resizable
定义一列的宽度是否可以调整,默认值为 true;
movable
属性定义是否可以拖动一列的位置, 默认值为 true;
horizontalAlignment
指定列标题文本的对齐方式,可以取 Text.AlignLeft (默认值)、Text.AlignRight、Text.AlignHCenter、Text.AlignJustify 四个值中的一个;
elideMode
指定标题不能完整显示时的省略方式,可以取 Text.ElideRight (默认值)、Text.ElideLeft、 Text.ElideMiddle、Text.ElideNone 四个值中的一个;
visible
布尔值,指定表格的一列是否显示,默认值为 true。
TableViewColumn 的最后一个属性是 delegate,指定一个组件用来绘制这一列,示例中没有指定,釆取了默认值;在你提供的 delegate 中,可以访问 styleData 的部分属性来获知相关信息。styleData 是 TableView 相关的风格数据,有很多属性。下面所列的属性可以在 TableViewColumn 的 delegate 中访问:
styleData.selected,当 Item 选中时为 true。
styleData.value,当前 Item 的文本。
styleData.textColor,Item 的默认颜色。
styleData.row,行索引。
styleData.column,列索引。
styleData.elideMode,列省略模式。
styleData.textAlignment,列文本对齐方式。
如你所见,我们仅仅是设置了 model,定义了表格的列属性,就得到了一个看起来还不错的表格,代码比我们使用 ListView 时少多了。
如果你觉得默认的表格样式不好看,还可以定制它们。
三、定制表格外观
通过设置 itemDelegate、rowDelegate、headerDelegate 等属性,可以定制表格的外观。
3.1 itemDelegate
itemDelegate 属性指定如何绘制每一个单元格,它的类型是 Component。在 itemDelegate 中可以访问的 styleData 属性与 TableViewColumn 的 delegate —样。下面是一个 itemDelegate 定义实例:
// 设置每个单元格的字体样式
itemDelegate: Text {
text: styleData.value
color: styleData.selected ? "red" : styleData.textColor
elide: styleData.elideMode
}
上面的 ItemDelegate 只有一个 Text 对象,它的 text 属性被设置为 styleData.value 。如果本 Item 被选中,文本颜色用红色,否则就用 styleData.textColor 文本如果显示不全,就采用 styleData.elideMode 指定的省略模式(在默认模式下省略号在右侧)。
itemDelegate 并不局限于一个简单的可见 Item,你可以组合多个可见元素来实现复杂的 itemDelegate,比如在单元格内放置一个复选框、一个图片等。
3.2 rowDelegate
rowDelegate 属性指定如何绘制行背景,它的高度将决定 TableView 的行高。 rowDelegate 可以访问下列 styleData 属性(你可以理解成每一行都有这些属性可用):
styleData.altemate,本行使用交替的背景颜色时为true。
styleData.selected,本行被选中时为 true。
styleData.row,本行的索引。
下面是一个 rowDelegate 实例:
// 设置行的背景色
rowDelegate: Rectangle {
color: styleData.selected ? root.highlight : root.alterBackground
}
在上面的 rowDelegate 中,我用一个 Rectangle 作为行背景元素,根据是否使用交替背景、是否选中为行指定了不同的背景色。
3.3 headerDelegate
headerDelegate 属性定义如何绘制表头,它可以访问下列 styleData 附加属性:
styleData.value,本 Item 的值。
styleData.column,本列索引。
styleData.pressed,本列被按下(如鼠标左键按下或手指按下)时为 true。
styleData.containsMouse,鼠标是否停在本列内。
styleData.textAlignment,本列文本的水平对齐方式。
下面是一个 headerDelegate 实例:
// 渐变色
property var normalG: Gradient {
GradientStop { position: 0.0; color: "#c7d3ac" }
GradientStop { position: 1.0; color: "#F0F0F0" }
}
property var hoverG: Gradient {
GradientStop { position: 0.0; color: "white"; }
GradientStop { position: 1.0; color: "#d7e3bc"; }
}
property var pressG: Gradient {
GradientStop { position: 0.0; color: "#d7e3bc"; }
GradientStop { position: 1.0; color: "white"; }
}
// ...
// 设置表头的样式
headerDelegate: Rectangle {
implicitWidth: 10
implicitHeight: 24
gradient: styleData.pressed ? root.pressG : (styleData.containsMouse ? root.hoverG: root.normalG)
border.width: 1
border.color: "gray"
Text {
anchors.verticalCenter: parent.verticalCenter
anchors.left: parent.left
anchors.leftMargin: 4
anchors.right: parent.right
anchors.rightMargin: 4
text: styleData.value
color: styleData.pressed ? "red" : "blue"
font.bold: true
}
}
我通过 headerDelegate 改变了默认的表头外观,使用渐变色来填充表头背景,为鼠标按下、经过定义了不同的背景颜色和文本颜色。
3.4 定制表格外观后的示例
现在让我们修改一下 phone_table_simple.qml 示例,为 TableView 添加 itemDelegate、 rowDelegate、headerDelegate,改变 TableView 的外观。新的 QML 文件是 phone_table_delegate.qml,内容如下:
import QtQuick 2.2
import QtQuick.Controls 1.2
Rectangle {
width: 360
height: 300
id: root
property var background: "#d7e3bc"
property var alterBackground: "white"
property var highlight: "#e4f7d6"
property var headerBkgnd: "#F0F0F0"
property var normalG: Gradient {
GradientStop { position: 0.0; color: "#c7d3ac" }
GradientStop { position: 1.0; color: "#F0F0F0" }
}
property var hoverG: Gradient {
GradientStop { position: 0.0; color: "white"; }
GradientStop { position: 1.0; color: "#d7e3bc"; }
}
property var pressG: Gradient {
GradientStop { position: 0.0; color: "#d7e3bc"; }
GradientStop { position: 1.0; color: "white"; }
}
TableView {
id: phoneTable
focus: true
anchors.fill: parent
TableViewColumn{ role: "name" ; title: "Name" ; width: 100; elideMode: Text.ElideRight;}
TableViewColumn{ role: "cost" ; title: "Cost" ; width: 100; }
TableViewColumn{ role: "manufacture" ; title: "manufacture" ; width: 140; }
// 设置每个单元格的字体样式
itemDelegate: Text {
text: styleData.value
color: styleData.selected ? "red" : styleData.textColor
elide: styleData.elideMode
}
// 设置行的背景色
rowDelegate: Rectangle {
color: styleData.selected ? root.highlight : root.alterBackground
}
// 设置表头的样式
headerDelegate: Rectangle {
implicitWidth: 10
implicitHeight: 24
gradient: styleData.pressed ? root.pressG : (styleData.containsMouse ? root.hoverG: root.normalG)
border.width: 1
border.color: "gray"
Text {
anchors.verticalCenter: parent.verticalCenter
anchors.left: parent.left
anchors.leftMargin: 4
anchors.right: parent.right
anchors.rightMargin: 4
text: styleData.value
color: styleData.pressed ? "red" : "blue"
font.bold: true
}
}
model: ListModel {
id: phoneModel
ListElement{
name: "rongyao2";
cost: "4900";
manufacture: "huawei"
}
ListElement{
name: "s6";
cost: "4800";
manufacture :"sumsung"
}
ListElement{
name: "apple5"
cost: "3300"
manufacture: "apple"
}
ListElement{
name: "Mi5"
cost: "3200"
manufacture: "xiaomi"
}
}
}
}
效果图如下:
四、动态增删改查 TabelView
有时你可能会想给 TableView 添加一列(一个字段),这时可以使用addColumn()方法, 其参数是 TableViewColumn,指向一个 TableViewColumn 实例,你可以动态创建这个实例。
对于前两节的示例,第三列可以这样添加进去:
Component.onCompleted: {
var col = Qt.createQmlObject("import QtQuick 2.2\nimport QtQuick.Controls 1.2\nTableViewColumn{ role: \"mamifacturer\"; title: \"Manufacturer\"; width: 140; }", phoneModel);
phoneTable.addColumn( col );
}
要想在指定位置添加一列,可以使用insertColumn(index, column)方法,index 参数指定列的索引,column 参数与 addColumn() 的参数一样。
如果你想删除某列,可以使用removeColumn(index)方法,指定列索引即可。
TableView 还提供了moveColumn(from, to),用于将一列从位置 from 移动到 to。
而如果你想给 TableView 动态添加数据,则可以通过调用 ListModel 的 append() 或 insert() 方法实现。删除数据通过 ListModel 的 clear() 或 remove() 方法实现。这些在前面介绍 ListView 的时候都已经介绍过了。
对于自定义的 Model,比如在 C++ 中实现的,则需要提供增、删、改数据的接口。 TableView 就介绍到这里了,进一步的应用请结合示例和 Qt 帮助学习。
参考:
《Qt Quick核心编程》第13章