1模型_视图(一)

一、模型视图原理

在Qt的界面中,常用到List、Table、Tree的数据结构视图。


列表数据图
表格数据图
树状数据视图

    实现上述三个数据结构视图有两种方式:一种是直接用QListWidget、QTreeWidget 和 QtableWidget 这种便利类。这种方式的优点是操作便捷、直观,缺点是可能会出现数据不同步的问题。另一种方式是model/view方式,即通过自定义数据结构、模型满足需要。对于新手而言,model/view可较为繁琐,但上手后将会极大提高程序的性能。两种方式与数据的交互方式完全不同,Widget通过相对于的Item项管理数据,便捷性较差;而model/view模式可以将数据集和视图分开管理,好处是一个model可以在多个view上使用,且开发者只需为model提供数据,而不必关心视图问题。

两种方式的区别

1 MVD模式介绍

     MVC 把图形界面分为三个部分:模型(Model)视图(View)控制器(Controller),在Qt中,这里的Contorller为Delegate代理,用于数据处理。

模型:用于管理数据,注意,数据不一定需要位于模型之中。
    Qt 使用抽象类 QAbstractItemModel 来描述模型,所有的模型都是通过子类化该抽像类而实现的。Qt 实现了一些标准的现成模型。

常用标准模型

部分标准模型解释

视图:就是呈现在用户面前的界面外观,视图负责把模型中的数据显示给用户。

     Qt 使用抽象类 QAbstractItemView 来描述视图,所有的视图都是通过子类化该抽像类而实现的。Qt 实现了一些标准的现成视图,比如 QListView(列表视图), QTableView(表格视图),QTreeView(树视图)等。

     QListWidget、QTreeWidget 和 QtableWidget 3个可用于数据编辑的组件。这 3 个类称为便利类(convenience classes),它们分别是 3 个视图类的子类,其层次关系如图 所示。

视图模型

数据:是一个统称,既可以是数据项也可以是数据元素。

数据项:是由多个数据元素组成的,每个数据元素都有自已的角色。

节点(单元格、项目):这三个概念通常用于指模型中的某一个数据项所在的位置,只是对于不同的模型结构会有不同的称呼,比如树形结构通常称为节点,表格结构通常称为单元格,而项目是一种更通用的称呼,Qt 中通常称其为项目(item)或数据项。

       QStandardItemModel model(3,3,this); //创建一个 3 行 3 列的表格结构的模型 
       QTableView v1;   //创建一个表格视图 
       //设置模型的数据,使用索引的形式设置每个数据项的值 
        model.setData(model.index(0,0),123); 
        model.setData(model.index(0,1),222); 
        model.setData(model.index(0,2),333); 
        model.setData(model.index(1,0),444); 
        model.setData(model.index(1,1),555); 
        model.setData(model.index(1,2),666); 
        model.setData(model.index(2,0),777); 
        model.setData(model.index(2,1),888); 
        model.setData(model.index(2,2),999); 
        v1.setModel(&model); //设置视图 v1 的模型 
        v1.show(); //显示视图 
为model提供数据

代理:处理用户在界面的交互数据操作。(将在后面介绍)

二、模型索引与数据角色

1模型结构

模型结构

    Qt 中,无论数据被存储为何种数据结构,模型总是以层次结构(即树形结构)来表示数据,视图按照此约定来访问模型中的数据,若数据是列表(list)或表格(tab)结构的数据,则可以把其看作是只含有顶层节点,不含任何子节点的树形结构。也就是说,我们在子类化QAbstractItemModel 来自定义自已的模型结构时,始终应以树形结构为出发点,来组织自已的模型结构

2模型索引与项的角色

    为了保证数据的表示与数据存取方式隔离,数据模型中引入了模型索引的概念。通过数据模型存取的每个数据都有一个模型索引,视图组件和代理都通过模型索引来获取数据。

    QModelIndex 表示模型索引的类。模型索引提供数据存取的一个临时指针,用于通过数据模型提取或修改数据。因为模型内部组织数据的结构随时可能改变,所以模型索引是临时的。如果需要使用持久性的模型索引,则要使用 QPersistentModelIndex 类。

2-1行号和列号

数据模型的基本形式是用行和列定义的表格数据,但这并不意味着底层的数据是用二维数组存储的,使用行和列只是为了组件之间交互方便的一种规定。通过模型索引的行号和列号就可以存取数据。在创建模型索引的函数中需要传递行号、列号和父项的模型索引。对于列表和表格模式的数据模型,顶层节点总是用 QModelIndex() 表示。

结构

①、树形结构:
//获取数据项 A 的模型索引,A 的父索引由一个无效模型索引指定。
QModelIndex A = model.index(0,0, QModelIndex());
//获取数据项 B 的模型索引,B 位于父索引 iA 的第 1 行第 1 列位置。
QModelIndex B = model.index(1,1, A);
QModelIndex C = model.index(1,1, QModelIndex());
②、表格结构
//获取数据项 B 的模型索引,B 是顶级数据项,因此其父索引是一个无效索引。
QModelIndex B = model.index(1,2, QModelIndex());
③、列表结构
//获取数据项 B 的模型索引,B 是顶级数据项,因此其父索引是一个无效索引。
QModelIndex B = model.index(1,0, QModelIndex());

2-2项的角色

    同一个类型的数据可以作为不同的角色(或作用)来使用,比如对于字符串"EEE",可把该字符串以文本的形式显示在视图的相应位置上,也可把该字符串作为工具提示使用,还可把该字符串作为 what's this 的帮助提示等。由此可见,数据的角色,决定了该数据在视图中的显示方式,角色不同,显示方式也不同。

项的介绍
项角色的部分
model.setData(model.index(0,1),222,Qt::DisplayRole); //设置显示的文本
model.setData(model.index(0,1),QIcon("F:/1i.png"),Qt::DecorationRole); //设置图标 
model.setData(model.index(0,1),"EEE",Qt::ToolTipRole); //设置工具提示

如果自己重载data函数,可以这样使用项角色


 QVariant MyModel::data(const QModelIndex &index, int role) const
 {
     int row = index.row();
     int col = index.column();
     // generate a log message when this method gets called
     qDebug() << QString("row %1, col%2, role %3")
             .arg(row).arg(col).arg(role);
     switch(role){
     case Qt::DisplayRole:
         if (row == 0 && col == 1) return QString("<--left");
         if (row == 1 && col == 1) return QString("right-->");

         return QString("Row%1, Column%2")
                 .arg(row + 1)
                 .arg(col +1);
         break;
     case Qt::FontRole:
         if (row == 0 && col == 0) 
         {
             QFont boldFont;
             boldFont.setBold(true);
             return boldFont;
         }
         break;
     case Qt::BackgroundRole:
         if (row == 1 && col == 2)  
         {
             QBrush redBackground(Qt::red);
             return redBackground;
         }
         break;
     case Qt::TextAlignmentRole:
         if (row == 1 && col == 1) 
         {
             return Qt::AlignRight + Qt::AlignVCenter;
         }
         break;
     case Qt::CheckStateRole:
         if (row == 1 && col == 0) //add a checkbox to cell(1,0)
         {
             return Qt::Checked;
         }
     }
     return QVariant();
 }

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,470评论 6 501
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,393评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 162,577评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,176评论 1 292
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,189评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,155评论 1 299
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,041评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,903评论 0 274
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,319评论 1 310
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,539评论 2 332
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,703评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,417评论 5 343
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,013评论 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,664评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,818评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,711评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,601评论 2 353