背景
由于在项目中需要实现treeview中的单元实现上下拖动功能,Qt Quick自身的treeview虽然能够实现树形结构功能,但却无法实现树形节点的拖动功能。于是考虑用listview来实现treeview的功能,在网上提的比较多的是listview+repeat方法,手动实践过,可以实现预期效果,但这个方法最大的缺点是如果有三个树形节点单元,在鼠标滚动时,listview的滚动条上的滑块定位不准而且时常的跳上跳下,已闭合的树形节点也会在滚动时被自动打开,数据量几千条时有时listview中的数据会跑飞,就是没有了。调试过发现滚动鼠标滚轮时会自动执行mousearea的doubleclicked事件,所以感觉这个方法不靠谱。
方法思路
于是考虑自己用listview+逻辑组合的方式实现treeview,即在model里面做好树形显示的一级节点二级节点组合,最后一次性加载到listview显示上就可以啦。将所有的一级节点放在一个list中,二级节点放在一级节点的后面。写一个类来存放当前数据节点信息,而
QList<NodeItem*> m_node_item_list;
用来存放其下一级节点信息。最后逐条添加到listview的model中即可。
树形model的加载方法可以借鉴下面的例子:如init_shoot_sequence_list_model()
,该函数可以根据传入的true 或false可实现treeview与纯listview的转换。
class NodeItem
{
// Q_OBJECT
public:
NodeItem( int n_node_id, int n_region_id, QString n_region_name, int n_parent_id, int n_device_id, QString s_device_content, int n_level);
int get_node_id() { return mn_node_id; }
int get_region_id() { return mn_region_id; }
QString get_region_name() { return ms_region_name; }
int get_parent_id() { return mn_parent_id; }
int get_device_id() { return mn_device_id; }
QString get_device_content() { return ms_device_content; }
int get_shoot_sequence_level() { return mn_level; }
QList<NodeItem*> m_node_item_list;
private:
int mn_node_id;
int mn_region_id;
QString ms_region_name;
int mn_parent_id;
int mn_device_id;
QString ms_device_content;
int mn_level;
};
import QtQuick 2.3
import QtQuick.Window 2.2
Window {
visible: true
width: 480
height: 640
Rectangle {
anchors.fill: parent
ListModel{
id: objmodel
}
Component {
id: shoot_sequence_delegate
Item {
id: unit_item
width: parent.width
height: 30
Row{
anchors.left: parent.left
anchors.verticalCenter: parent.verticalCenter
spacing: 8
Text {
id: tag_txt
text: tag
color: unit_item.ListView.isCurrentItem? "blue":"black"
font.pixelSize: 20
}
Text {
id: name_txt
text: name
color: unit_item.ListView.isCurrentItem? "blue":"black"
font.pixelSize: 20
}
}
MouseArea {
id: mousearea
anchors.fill: parent
onClicked: {
shoot_sequence_listview.currentIndex = index
}
onDoubleClicked: {
shoot_sequence_listview.currentIndex = index
var data = objmodel.get(shoot_sequence_listview.currentIndex);
if( data.level_status === "0" ) {
var n = data.model_index
var n_device_node_count = shoot_sequences_list_model.get_device_node_count_from_list( data.model_index )
if( data.visible_status === "true" ) {
objmodel.setProperty(shoot_sequence_listview.currentIndex, "visible_status", "false")
objmodel.setProperty(shoot_sequence_listview.currentIndex, "tag", "+")
objmodel.remove( shoot_sequence_listview.currentIndex+1, n_device_node_count )
} else {
objmodel.setProperty(shoot_sequence_listview.currentIndex, "visible_status", "true")
objmodel.setProperty(shoot_sequence_listview.currentIndex, "tag", "-")
for( var j=0; j<n_device_node_count; j++ ) {
var n_node_id = shoot_sequences_list_model.get_node_id_from_list( n, j )
var n_region_id = shoot_sequences_list_model.get_region_id_from_list( n, j )
var s_region_name = shoot_sequences_list_model.get_region_name_from_list( n, j )
var n_parent_id = shoot_sequences_list_model.get_parent_id_from_list( n, j )
var n_device_id = shoot_sequences_list_model.get_device_id_from_list( n, j )
var s_device_content = shoot_sequences_list_model.get_device_content_from_list( n, j )
var n_shoot_level = shoot_sequences_list_model.get_shoot_sequence_level_from_list( n, j )
objmodel.insert(shoot_sequence_listview.currentIndex+j+1, {"name":""+s_device_content, "tag":" ", "level_status":""+n_shoot_level, "regin_id": n_region_id, "visible_status":"true", "visible_status":"true", "model_index":""+n})
}
}
}
}
}
}
}
property int flag: 0
ListView {
id: shoot_sequence_listview
anchors.fill: parent
delegate: shoot_sequence_delegate
model:objmodel
interactive: false
focus: true
Component.onCompleted: {
// shoot_sequences_list_model.set_shoot_sequence_list_model( "26", true );
// init_shoot_sequence_list_model( true )
shoot_sequences_list_model.set_shoot_sequence_list_model( "26", false );
init_shoot_sequence_list_model( false )
}
function init_shoot_sequence_list_model( b_last_level_status ) {
objmodel.clear()
if( b_last_level_status ) {
var n_list_count = shoot_sequences_list_model.get_shoot_sequence_list_model_count()
for( var i=0; i<n_list_count; i++ ) {
var node_id = shoot_sequences_list_model.get_node_id( i )
var region_id = shoot_sequences_list_model.get_region_id( i )
var region_name = shoot_sequences_list_model.get_region_name( i )
var parent_id = shoot_sequences_list_model.get_parent_id( i )
var device_id = shoot_sequences_list_model.get_device_id( i )
var device_content = shoot_sequences_list_model.get_device_content( i )
var shoot_level = shoot_sequences_list_model.get_shoot_sequence_level( i )
objmodel.append({"name":""+device_content, "tag":" ", "level_status":""+shoot_level, "regin_id": region_id, "visible_status":"true", "model_index":"-1"})
}
} else {
var n_region_list_count = shoot_sequences_list_model.get_shoot_sequence_list_model_count()
var n_device_node_count;
for( var n=0; n<n_region_list_count; n++ ) {
node_id = shoot_sequences_list_model.get_node_id( n )
region_id = shoot_sequences_list_model.get_region_id( n )
region_name = shoot_sequences_list_model.get_region_name( n )
parent_id = shoot_sequences_list_model.get_parent_id( n )
device_id = shoot_sequences_list_model.get_device_id( n )
device_content = shoot_sequences_list_model.get_device_content( n )
shoot_level = shoot_sequences_list_model.get_shoot_sequence_level( n )
objmodel.append({"name":region_name, "tag":"-", "level_status":""+shoot_level, "regin_id": region_id, "visible_status":"true", "model_index":""+n})
n_device_node_count = shoot_sequences_list_model.get_device_node_count_from_list( n )
console.log("n_device_node_count: "+n_device_node_count)
for( var j=0; j<n_device_node_count; j++ ) {
var n_node_id = shoot_sequences_list_model.get_node_id_from_list( n, j )
var n_region_id = shoot_sequences_list_model.get_region_id_from_list( n, j )
var s_region_name = shoot_sequences_list_model.get_region_name_from_list( n, j )
var n_parent_id = shoot_sequences_list_model.get_parent_id_from_list( n, j )
var n_device_id = shoot_sequences_list_model.get_device_id_from_list( n, j )
var s_device_content = shoot_sequences_list_model.get_device_content_from_list( n, j )
var n_shoot_level = shoot_sequences_list_model.get_shoot_sequence_level_from_list( n, j )
objmodel.append({"name":""+s_device_content, "tag":" ", "level_status":""+n_shoot_level, "regin_id": n_region_id, "visible_status":"true", "model_index":""+n})
}
}
}
}
}
}
}