Qt model/View

 Qt包含一组使用模型/视图结构的类,可以用来管理数据并呈现给用户。这种体系结构引入的分离使开发人员更灵活地定制项目,并且提供了一个标准模型的接口,以允许广泛范围的数据源被使用到到现有的视图中。
      模型 - 视图 - 控制器(MVC)是一种设计模式,由三类对象组成:
  • 模型:应用程序对象。
  • 视图:屏幕演示。
  • 控制器:定义了用户界面响应用户输入的方式。
      如果视图和控制器对象相结合,其结果是模型/视图结构,仍然分离了数据与呈现给用户的方式,但提供了基于相同原理的简单框架。这种分离使得它可以在几个不同的视图中显示相同的数据,并且实现新类型的视图,而无需改变底层的数据结构。为了灵活地处理用户输入,则引入了委托的概念。在此框架引入委托的优点是:它允许项目数据显示和自定义编辑。


      模型与数据源进行通信,在这个体系结构中为其它组件提供了一个接口。通信的性质依赖于数据源的类型以及模型的实现方式。
      视图从模型中得到模型索引,这些都引用到数据项。通过为模型提供模型索引,视图可以从数据源中检索数据项。
      在标准的视图里,委托呈现数据项目。当一个项目被编辑,委托与模型直接利用模型索引进行通信。

模型/视图/委托通信
      模型、视图、委托使用信号和槽相互通信:
  • 模型的信号:通知视图关于改变由数据源保持的数据。
  • 视图的信号:提供了关于用户交互显示的项目信息。
  • 委托的信号:当编辑时告诉模型和视图编辑器的状态。
模型
      所有的模型都基于QAbstractItemModel类。这个类定义了一个使用视图和委托来访问数据的接口。数据本身不是必须要存储在模型中,可以在一个数据结构或一个单独的类、文件、数据库、或其它一些应用组件。
      QAbstractItemModel为数据提供了一个接口,它足够的灵活性来处理表格、列表、树形式的数据视图。然而,实现新的列表和类似于表的数据结构模型时,QAbstractListModel和QAbstractTableModel类是更好的起点,因为它们提供了适当的常用的功能的默认实现。这些类可以派生子类,用来提供支持特定种类的列表和表格的模型。
 Qt提供了一些现成的模型,可以用来处理数据项:
  • QStringListModel:用于存储简单的QString的列表项。
  • QStandardItemModel:管理更复杂的树结构件,其中每一个项目可以包含任意数据。
  • QFileSystemModel:提供有关本地文件系统的文件和目录信息。
  • QSqlQueryModel、QSqlTableModel、QSqlRelationalTableModel:使用模型/视图约定来访问数据库。
      如果这些标准模型不能满足要求,则可以继承化QAbstractItemModel、QAbstractListModel或QAbstractTableModel来创建自定义模型。

视图
      提供了完整的实现为各种不同的视图:而 QListView 显示项目列表, QTableView 中从一个表模型中显示数据, QTreeView 则显示了层次列表的数据模型项目。每个类是基于QAbstractItemView抽象基类。虽然这些类是准备使用的实现,他们也可以被子类化,以提供自定义的视图。

委托
      QAbstractItemDelegate在模型/视图框架中代表抽象的基类。默认的委托实现由QStyledItemDelegate提供,这被Qt的标准视图用作默认的委托。然而,QStyledItemDelegate和QItemDelegate独立替代绘画,且为视图项提供编辑器。它们之间的区别在于QStyledItemDelegate使用当前样式来绘制项目。因此,建议实现自定义委托或当与Qt样式表一起使用时,使用QStyledItemDelegate作为基类。

使用视图与现有的模型




基本概念
    在模型/视图结构中,模型提供了视图与委托访问数据的标准接口。在Qt中,标准的接口由QAbstractItemModel类定义。无论多么数据项被存储在任何底层的数据结构中,QAbstractItemModel的所有子类所代表的数据作为包含视图项的分层结构。视图使用这个约定来访问模型中的数据项,但并不限制将该信息传达给用户的方式。
 
 
Model indexes
 
 
    为确保数据被分开被访问,模型索引的概念被引入。可以通过模型索引来获得每条信息。视图与委托使用这些索引来请求显示的数据项。
    因此,模型只需要知道如何获取数据,并通过模型管理的数据的类型可以被相当普遍定义。型号索引包含一个指向创建它们的模型的指针,在处理多个模型时可以防止混乱。
    QAbstractItemModel *model = index.model();
    模型索引提供临时参考信息,并且可以用于通过模型来检索或修改数据。由于模型可能重组其内部结构,模型的索引可能会变得无效,不宜存储。如果需要长期参考一条信息,必须创建一个持久性模型索引。这为模型保持最新信息提供了一个参考。临时模型索引由QModelIndex类提供,持久性模型索引由QPersistentModelIndex类提供。
    取得对应于数据项的模型索引,模型中必须制定三个属性:一个行号、一个列号,以及父项的模型索引。
行和列
    在最基本的形式中,模型可以被一个简单的表访问,表项位于行号和列号,这并不意味着底层数据存储在数据结构中,使用行号和列号只是一个惯例,以允许组件相互通信。我们可以通过指定行号和列号的模型索引有关的任何特定信息,通过下面的方式得到项目的索引:
    QModelIndex index = model->index(row, column, ...);
    模型提供的接口简单,单级的数据结构如列表和表格不需要提供任何其他信息。但是,正如上面的代码所示,当获得一个模型索引时,我们需要提供更多的信息。
 由模型提供的类似于表的接口给数据项是理想的当在表格或列表视图中使用数据,行号和列号准确地映射到视图显示项目的方式。然而,结构,如树视图需要更模型为项目暴露一个更灵活的接口。因此,每个项目也可以是另一个表的父项,大致相同的方式,在一个树视图中的顶级项目可以包含另一个列表项。
    当请求的一个模型项的索引时,必须提供有关该项目的父项目的一些信息。在模型外,指定一个项目的唯一途径是通过一个模型索引,所以父模型索引也必须如下给出:
    QModelIndex index = model->index(row, column, parent);
父项,行和列
    该图显示了一个树模型,其中每个项目都依赖于由一个父项,一个行号和一个列号。
    项目的“A”和“C”表示模型顶层的兄弟姐妹:
 
  
    项目“A”有很多孩子,可以通过如下方式由“A”索引得到“B”索引:
    QModelIndex indexB = model->index(1, 0, indexA);
    QModelIndex indexA = model->index(0, 0, QModelIndex());
    QModelIndex indexC = model->index(2, 1, QModelIndex());
使用模型索引
 
  
    为了演示如何将数据从一个模型中进行检索,使用模型索引,我们创建了一个QFileSystemModel,在窗体上没有视图以及显示文件和目录的名称。虽然这并不是使用模型的正常方式,它表明模型在处理模型索引上的约定。
    我们用以下述方式构建了一个文件系统模型:
 
  
    QFileSystemModel *model = new QFileSystemModel;
    QModelIndex parentIndex = model->index(QDir::currentPath());
    int numRows = model->rowCount(parentIndex);
 
  
    在这种情况下,我们设置了一个默认QFileSystemModel,由该模型使用index()的特定实现来获取父索引,使用rowCount()函数来计算行号。
    为简单起见,我们只关心模型中的第一列中的项目。我们检查每一行,依次获取每一行中的第一个项目的模型索引,以及读出所存储在该模型	项目中的数据。
 
  
    for (int row = 0; row <<span style=" color:#c0c0c0;"> numRows; ++row) {
        QModelIndex index = model->index(row, 0, parentIndex);
    为了获得一个模型索引,我们指定了行号、列号(第一列为零),以及所有我们想要的项目的父项目的模型索引。每个项目中的文本检索可以	使用模型的data()函数来获取。我们指定了模型索引和Qt::DisplayRole来获取数据项中的字符串。
 
  
        QString text = model->data(index, Qt::DisplayRole).toString();
        // Display the text in a widget.
    }
 
  
使用模型
 
  
    我们创建一个字符串列表模型作为例子,设置一些数据,并构造一个视图来显示模型的内容。这都可以在一个单一的函数执行:
 
  
 
  
	int main(int argc, char *argv[])
	{	
    	QApplication app(argc, argv);
    	QStringList numbers;
    	numbers << "One" << "Two" << "Three" << "Four" << "Five";
    	QAbstractItemModel *model = new QStringListModel(numbers);
    	QListView *view = new QListView;
    	view->setModel(model);
 
  
   	 	//视图正常显示方式
    	view->show();
    	return app.exec();
	}
一个模型的多个视图
      一个模型可以为多个视图所使用。在下面的代码中,我们创建两个表视图,使用的均是创建好的同一个模型。
    QTableView *firstTableView = new QTableView;
    QTableView *secondTableView = new QTableView;
    firstTableView->setModel(model);
    secondTableView->setModel(model);
视图共享选择
 
  
    虽然视图类提供自己的默认选择模型很方便,但当我们使用多个视图到同一个模型时,通常需要所有的模型数据和用户的选择在所有视图显示一致。由于视图类允许其内部选择模型进行更换,那么可以使用如下方式实现视图之间的统一:
    secondTableView->setSelectionModel(firstTableView->selectionModel());
    第二个视图给出了第一个视图的选择模型。这两种视图现在在同一个选择模型进行操作,保持了数据和所选项目的同步。
 
  
 
  
 
  


  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值