pbootcms网站模板|日韩1区2区|织梦模板||网站源码|日韩1区2区|jquery建站特效-html5模板网

Qt 5.2 Model-View-Pattern:如何通知模型對(duì)象底層數(shù)據(jù)結(jié)

Qt 5.2 Model-View-Pattern: How to inform model object about changes in underlying data structure(Qt 5.2 Model-View-Pattern:如何通知模型對(duì)象底層數(shù)據(jù)結(jié)構(gòu)的變化)
本文介紹了Qt 5.2 Model-View-Pattern:如何通知模型對(duì)象底層數(shù)據(jù)結(jié)構(gòu)的變化的處理方法,對(duì)大家解決問題具有一定的參考價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)吧!

問題描述

我有一個(gè)類用于永久存儲(chǔ)一些以表格方式組織的項(xiàng)目.這個(gè)類與 Qt 完全無關(guān),來自不同的庫(kù).對(duì)于這個(gè)問題的其余部分,讓我們調(diào)用這個(gè)類 DataContainer.它提供了與 std-c++ 兼容的迭代器來訪問和操作內(nèi)容.

I have a class used for permanent storage of some item that are organized in a table-like manner. This class is totally unrelated to Qt and comes from a different library. Lets call this class DataContainer for the rest of this question. It provides std-c++ compatible iterators to access and manipulate the content.

我需要通過 Qt GUI 顯示和修改該數(shù)據(jù).我的想法是創(chuàng)建一個(gè)類 DataContainerQtAdaptor,它繼承自 QAbstractTableModel 并存儲(chǔ)一個(gè)指向 DataContainer 對(duì)象的指針.DataContainerQtAdaptor 用作 DataContainer 對(duì)象的適配器,我的 Qt 應(yīng)用程序內(nèi)部的所有操作都通過此適配器完成.然后我使用 QTableView 小部件來顯示信息.

I need to display and modify that data through a Qt GUI. My idea was to create a class DataContainerQtAdaptor that inherits from QAbstractTableModel and stores a pointer to the DataContainer object. The DataContainerQtAdaptor serves as an adaptor to the DataContainer object and all manipulation from inside of my Qt app is done through this adaptor. Then I use a QTableView widget to display the information.

不幸的是,DataContainer 可能會(huì)被線程/進(jìn)程更改.(例如,將 DataContainer 視為封裝數(shù)據(jù)庫(kù)連接的某個(gè) C++ 類,并且該數(shù)據(jù)庫(kù)可能會(huì)被其他人更改.)

Unfortunately the DataContainer might be changed by threads/processes. (For example think of DataContainer as some C++ class that encapsulates a database connection and that database might be changed by someone else.)

問題:

1) 假設(shè)我有一個(gè)函數(shù),每次 DataContainer 對(duì)象的內(nèi)部結(jié)構(gòu)發(fā)生變化時(shí)都會(huì)調(diào)用該函數(shù).必須調(diào)用 QAbstractTableModel 來通知模型底層更改的正確函數(shù)是什么?我需要類似親愛的模型,您的持久存儲(chǔ)后端已更改.請(qǐng)更新自己并向每個(gè)附加視圖發(fā)出信號(hào)以反映此更改".

1) Assume I have a function that is called everytime the internal structur of the DataContainer object has been changed. What is the correct function of the QAbstractTableModel that must be called to inform the model of the underlying change? I need something like "Dear Model, your persistent storage backend changed. Please, update yourself and emit a signal to every attached view in order to reflect this change".

2) 假設(shè) 1) 已解決.如果更改是通過 GUI 觸發(fā)的,那么避免雙重"GUI 更新的最佳方法是什么?例如:用戶單擊表格小部件中的單元格 -> 表格小部件調(diào)用模型的 setData -> 模型將更改推送到后端 -> 后端觸發(fā)其自己的onUpdate"功能 -> 模型重新讀取完整的后端(盡管它已經(jīng)知道更改)-> 第二次更新 GUI

2) Lets say 1) is solved. What is the best way to avoid a "double" GUI update in case the change was triggered through the GUI? E.g: User clicks on a cell in the table widget -> table widget calls setData of the model -> model pushes change to backend -> backend triggers its own "onUpdate" function -> model re-reads complete backend (although it already knows the change) -> GUI is updated a second time

3) 用戶應(yīng)該能夠通過 GUI 插入新的行/列并將數(shù)據(jù)放入其中.但是位置是由這個(gè)數(shù)據(jù)決定的,因?yàn)楹蠖吮3謹(jǐn)?shù)據(jù)的排序.因此,我有以下問題:用戶決定在最后創(chuàng)建一個(gè)新行,并將新數(shù)據(jù)推送到后端.當(dāng)重新讀取后端/模型時(shí),此數(shù)據(jù)通常不在最后位置,而是已插入中間某處,并且所有其他數(shù)據(jù)已向前移動(dòng).我如何保持表格視圖小部件的所有屬性(如選擇單元格")同步?

3) The user should be able to insert new rows/columns through the GUI and put data into it. But the position is detemined by this data, because the backend keeps the data sorted. Hence, I have the following problem: The user decides to create a new row at the end and the new data is pushed to the backend. When the backend/model is re-read this data is normally not at the last position, but has been inserted somewhere in the middle and all other data has been moved forward. Ho do I keep all the properties of the the table view widget like "selection of a cell" in sync?

我相信,對(duì)于所有這些問題,一定有一些簡(jiǎn)單的標(biāo)準(zhǔn)解決方案,因?yàn)樗c QFileSystemModel 的工作方式相同.用戶選擇一個(gè)文件,其他一些進(jìn)程創(chuàng)建一個(gè)新文件.新文件顯示在視圖中,所有后續(xù)行向前移動(dòng).選擇也向前推進(jìn).

I believe, there must be some simple standard solution to all these question, because it is the same way as QFileSystemModel works. The user selects a file and some other process creates a new file. The new file is displayed in the view and all subsequent rows move forward. The selection moves forward, too.

馬蒂亞斯

推薦答案

模型語(yǔ)義

首先要保證QAbstractItemModel不能處于不一致的狀態(tài).這意味著必須在模型上觸發(fā)一些信號(hào), 在對(duì)基礎(chǔ)數(shù)據(jù)進(jìn)行某些更改之前.

Model Semantics

First of all, you must ensure that the QAbstractItemModel cannot be in an inconsistent state. This means that there are some signals that must be fired on the model before certain changes to the underlying data are done.

結(jié)構(gòu)更改和數(shù)據(jù)更改之間存在根本區(qū)別.結(jié)構(gòu)更改是添加或刪除模型的行/列.數(shù)據(jù)更改僅影響現(xiàn)有數(shù)據(jù)項(xiàng)的值.

There is a fundamental difference between changes to structure and changes to data. Structure changes are the rows/columns of the model being added or removed. Data changes affect the value of existing data items only.

  • 結(jié)構(gòu)更改需要在修改前后調(diào)用 beginXxxendXxx.在調(diào)用 beginXxx 之前,您不能修改任何結(jié)構(gòu).完成結(jié)構(gòu)更改后,調(diào)用 endXxx.Xxx 是以下之一:InsertColumnsMoveColumnsRemoveColumnsInsertRowsMoveRowsRemoveRowsResetModel.

  • Structural changes require calling beginXxx and endXxx around the modification. You cannot modify any structure before calling beginXxx. When you're done changing the structure, call endXxx. Xxx is one of: InsertColumns, MoveColumns, RemoveColumns, InsertRows, MoveRows, RemoveRows, ResetModel.

如果更改影響許多不連續(xù)的行/列,則指示模型重置會(huì)更便宜 - 但要注意視圖上的選擇可能無法生存.

If the changes affect many discontiguous rows/columns, it's cheaper to indicate a model reset - but be wary that selections on the views might not survive it.

保持結(jié)構(gòu)完整的數(shù)據(jù)更改只需要在修改基礎(chǔ)數(shù)據(jù)之后發(fā)送dataChanged.這意味著在查詢模型的對(duì)象接收到 dataChanged 之前,對(duì) data 的調(diào)用可能會(huì)返回一個(gè)新值.

Data changes that keep the structure intact merely require that dataChanged is sent after the underlying data was modified. This means that there is a window of time when a call to data might return a new value before dataChanged is received by the object that queries the model.

這也意味著非QObject 類中的非常量模型幾乎沒有用,除非您當(dāng)然使用觀察者或類似模式實(shí)現(xiàn)橋接功能.

This also implies that non-constant models are almost useless from non-QObject classes, unless of course you implement bridge functionality using observer or similar patterns.

處理模型更新循環(huán)的 Qt 慣用方法是利用項(xiàng)目角色.模型如何解釋角色完全取決于您.QStringListModel 實(shí)現(xiàn)的一個(gè)簡(jiǎn)單而有用的行為是將角色從 setData 調(diào)用轉(zhuǎn)發(fā)到 dataChanged,否則忽略該角色.

The Qt-idiomatic way of dealing with update loops on the model is by leveraging the item roles. It's entirely up to you how your model interprets the roles. A simple and useful behavior implemented by QStringListModel is simply to forward the role from the setData call to dataChanged, otherwise ignoring the role.

股票視圖小部件僅對(duì)帶有 DisplayRoledataChanged 做出反應(yīng).然而,當(dāng)他們編輯數(shù)據(jù)時(shí),他們使用 EditRole 調(diào)用 setData.這打破了循環(huán).該方法既適用于查看小部件,也適用于 Qt 快速查看項(xiàng)目.

The stock view widgets react only to dataChanged with the DisplayRole. Yet, when they edit the data, they call setData with the EditRole. This breaks the loop. The approach is applicable both to view widgets and to Qt Quick view items.

只要模型在排序完成時(shí)正確地發(fā)出變化信號(hào),你就會(huì)沒事.

As long as the model properly emits the change signals when the sorting is done, you'll be fine.

操作順序?yàn)?

  1. 視圖添加一行并調(diào)用模型的insertRow 方法.該模型可以將此空行添加到底層容器中,也可以不添加.關(guān)鍵是必須暫時(shí)保留空行索引.

  1. The view adds a row and calls model's insertRow method. The model can either add this empty row to the underlying container or not. The key is that the empty row index must be kept for now.

編輯從行中的一個(gè)項(xiàng)目開始.視圖狀態(tài)更改為 Editing.

The editing starts on an item in the row. The view state changes to Editing.

對(duì)項(xiàng)目進(jìn)行編輯.視圖退出編輯狀態(tài),并在模型上設(shè)置數(shù)據(jù).

Editing is done on the item. The view exits the editing state, and sets the data on the model.

模型根據(jù)項(xiàng)目的內(nèi)容確定項(xiàng)目的最終位置.

The model determines the final position of the item, based on its contents.

模型調(diào)用beginMoveRows.

模型通過在正確的位置插入項(xiàng)目來改變?nèi)萜?

The model changes the container by inserting the item at the correct location.

模型調(diào)用endMoveRows.

此時(shí),一切都如您所愿.如果在移動(dòng)之前獲得焦點(diǎn),則視圖可以自動(dòng)跟隨移動(dòng)的項(xiàng)目.默認(rèn)情況下,編輯的項(xiàng)目具有焦點(diǎn),因此效果很好.

At this point, everything is as you expect it to be. The views can automatically follow the moved item if it was focused prior to being moved. The edited items are focused by default, so that works fine.

您的DataContainer 沒有足夠的功能使其工作除非對(duì)它的所有訪問都通過模型完成.如果你想直接訪問容器,要么讓容器顯式繼承QAbstractXxxxModel,要么你必須給容器添加一個(gè)通知系統(tǒng).前者是更簡(jiǎn)單的選擇.

Your DataContainer doesn't have enough functionality to make it work unless all access to it were to be done through the model. If you want to access the container directly, either make the container explicitly inherit QAbstractXxxxModel, or you'll have to add a notification system to the container. The former is an easier option.

您的核心問題簡(jiǎn)化為:我能否在不實(shí)現(xiàn)模型通知 API 的某些變體的情況下?lián)碛心P凸δ?顯而易見的答案是:不,對(duì)不起,你不能——根據(jù)定義.要么功能存在,要么不存在.如果您不希望容器成為 QObject,您可以使用觀察者模式實(shí)現(xiàn)通知 API - 那么您將需要您的模型填充類.真的沒有辦法.

Your core question reduces to: can I have model functionality without implementing some variant of the model notification API. The obvious answer is: no, sorry, you can't - by definition. Either the functionality is there, or it isn't. You can implement the notification API using an observer pattern if you don't want the container to be a QObject - then you'll need your model shim class. There's really no way around it.

QFileSystemModel 由文件系統(tǒng)通知有關(guān)已更改的單個(gè)目錄條目.你的容器也必須這樣做——這相當(dāng)于以某種形狀或形式提供一個(gè) dataChanged 信號(hào).如果模型有被移動(dòng)或添加/刪除的項(xiàng)目 - 它的結(jié)構(gòu)發(fā)生了變化 - 它必須通過調(diào)用相關(guān)的 beginZzz 來發(fā)出 xxxAboutToBeYyyxxxYyy 信號(hào)endZzz 方法.

The QFileSystemModel gets notified by the filesystem about individual directory entries that have changed. Your container has to do the same - and this amounts to providing a dataChanged signal, in some shape or form. If the model has items that get moved around or added/removed - its structure changes - it has to emit the xxxAboutToBeYyy and xxxYyy signals, by calling the relevant beginZzz and endZzz methods.

QModelIndex 最重要的未記錄方面是:它的實(shí)例僅在模型結(jié)構(gòu)沒有改變時(shí)才有效.如果您的模型傳遞了在結(jié)構(gòu)更改之前生成的索引,您就可以自由地以未定義的方式行事(崩潰、發(fā)動(dòng)核打擊等).

The most important underdocumented aspect of QModelIndex is: its instances are only valid for as long as the model's structure hasn't changed. If your model is passed an index that was generated prior to a structure change, you're free to behave in an undefined way (crash, launch a nuclear strike, whatever).

QModelIndex::internalPointer() 存在的全部原因是您擁有一個(gè)基礎(chǔ)的、復(fù)雜索引的數(shù)據(jù)容器的用例.模型的 createIndex 方法的實(shí)現(xiàn)必須生成索引實(shí)例,以某種形式存儲(chǔ)對(duì) DataContainer 索引的引用.如果這些索引適合指針,則不需要在堆上分配數(shù)據(jù).如果需要在堆上分配容器索引存儲(chǔ),則必須保留指向此數(shù)據(jù)的指針,并在容器結(jié)構(gòu)發(fā)生變化時(shí)將其刪除.您可以隨意執(zhí)行此操作,因?yàn)樵诮Y(jié)構(gòu)更改后沒有人應(yīng)該使用索引實(shí)例.

The whole reason for the existence of QModelIndex::internalPointer() is your use case of having an underlying, complex-indexed data container. Your implementation of the model's createIndex method must generate index instances that store references to the DataContainer's indices in some form. If those indices fit in a pointer, you don't need to allocate the data on the heap. If you need to allocate the container index storage on the heap, you must retain a pointer to this data and delete it any time the container's structure changes. You're free to do it, since nobody is supposed to use the index instance after a structure change.

這篇關(guān)于Qt 5.2 Model-View-Pattern:如何通知模型對(duì)象底層數(shù)據(jù)結(jié)構(gòu)的變化的文章就介紹到這了,希望我們推薦的答案對(duì)大家有所幫助,也希望大家多多支持html5模板網(wǎng)!

【網(wǎng)站聲明】本站部分內(nèi)容來源于互聯(lián)網(wǎng),旨在幫助大家更快的解決問題,如果有圖片或者內(nèi)容侵犯了您的權(quán)益,請(qǐng)聯(lián)系我們刪除處理,感謝您的支持!

相關(guān)文檔推薦

How can I read and manipulate CSV file data in C++?(如何在 C++ 中讀取和操作 CSV 文件數(shù)據(jù)?)
In C++ why can#39;t I write a for() loop like this: for( int i = 1, double i2 = 0; (在 C++ 中,為什么我不能像這樣編寫 for() 循環(huán): for( int i = 1, double i2 = 0;)
How does OpenMP handle nested loops?(OpenMP 如何處理嵌套循環(huán)?)
Reusing thread in loop c++(在循環(huán) C++ 中重用線程)
Precise thread sleep needed. Max 1ms error(需要精確的線程睡眠.最大 1ms 誤差)
Is there ever a need for a quot;do {...} while ( )quot; loop?(是否需要“do {...} while ()?環(huán)形?)
主站蜘蛛池模板: 粘度计NDJ-5S,粘度计NDJ-8S,越平水分测定仪-上海右一仪器有限公司 | 气动调节阀,电动调节阀,自力式压力调节阀,切断阀「厂家」-浙江利沃夫自控阀门 | 微学堂-电动能源汽车评测_电动车性能分享网 | 螺旋叶片_螺旋叶片成型机_绞龙叶片_莱州源泽机械制造有限公司 | 篮球架_乒乓球台_足球门_校园_竞技体育器材_厂家_价格-沧州浩然体育器材有限公司 | 气力输送_输送机械_自动化配料系统_负压吸送_制造主力军江苏高达智能装备有限公司! | 液压升降平台_剪叉式液压/导轨式升降机_传菜机定做「宁波日腾升降机厂家」 | 碳刷_刷握_集电环_恒压簧_电刷厂家-上海丹臻机电科技有限公司 | 深圳美安可自动化设备有限公司,喷码机,定制喷码机,二维码喷码机,深圳喷码机,纸箱喷码机,东莞喷码机 UV喷码机,日期喷码机,鸡蛋喷码机,管芯喷码机,管内壁喷码机,喷码机厂家 | 空冷器|空气冷却器|空水冷却器-无锡赛迪森机械有限公司[官网] | 尼龙PA610树脂,尼龙PA612树脂,尼龙PA1010树脂,透明尼龙-谷骐科技【官网】 | 尚为传动-专业高精密蜗轮蜗杆,双导程蜗轮蜗杆,蜗轮蜗杆减速机,蜗杆减速机生产厂家 | 不锈钢螺丝 - 六角螺丝厂家 - 不锈钢紧固件 - 万千紧固件--紧固件一站式采购 | 二手注塑机回收_旧注塑机回收_二手注塑机买卖 - 大鑫二手注塑机 二手光谱仪维修-德国OBLF光谱仪|进口斯派克光谱仪-热电ARL光谱仪-意大利GNR光谱仪-永晖检测 | 至顶网| 河南新乡德诚生产厂家主营震动筛,振动筛设备,筛机,塑料震动筛选机 | 重庆LED显示屏_显示屏安装公司_重庆LED显示屏批发-彩光科技公司 重庆钣金加工厂家首页-专业定做监控电视墙_操作台 | 截齿|煤截齿|采煤机截齿|掘进机截齿|旋挖截齿-山东卓力截齿厂家报价 | 帽子厂家_帽子工厂_帽子定做_义乌帽厂_帽厂_制帽厂 | 【同风运车官网】一站式汽车托运服务平台,验车满意再付款 | 挨踢网-大家的导航!| 钢绞线万能材料试验机-全自动恒应力两用机-混凝土恒应力压力试验机-北京科达京威科技发展有限公司 | 不锈钢反应釜,不锈钢反应釜厂家-价格-威海鑫泰化工机械有限公司 不干胶标签-不干胶贴纸-不干胶标签定制-不干胶标签印刷厂-弗雷曼纸业(苏州)有限公司 | 制氮设备_PSA制氮机_激光切割制氮机_氮气机生产厂家-苏州西斯气体设备有限公司 | 沥青灌缝机_路面灌缝机_道路灌缝机_沥青灌缝机厂家_济宁萨奥机械有限公司 | 电机保护器-电动机综合保护器-上海硕吉电器有限公司 | 厦门ISO认证|厦门ISO9001认证|厦门ISO14001认证|厦门ISO45001认证-艾索咨询专注ISO认证行业 | 搜木网 - 木业全产业链交易平台,免费搜货、低价买货! | 磁力轮,磁力联轴器,磁齿轮,钕铁硼磁铁-北京磁运达厂家 | 螺杆式冷水机-低温冷水机厂家-冷冻机-风冷式-水冷式冷水机-上海祝松机械有限公司 | 烟雾净化器-滤筒除尘器-防爆除尘器-除尘器厂家-东莞执信环保科技有限公司 | 厂房出租_厂房出售_产业园区招商_工业地产 - 中工招商网 | 西安标准厂房_陕西工业厂房_西咸新区独栋厂房_长信科技产业园官方网站 | 膜结构_ETFE膜结构_膜结构厂家_膜结构设计-深圳市烨兴智能空间技术有限公司 | 生产自动包装秤_颗粒包装秤_肥料包装秤等包装机械-郑州鑫晟重工科技有限公司 | 北京网站建设|北京网站开发|北京网站设计|高端做网站公司 | 无锡网站建设_小程序制作_网站设计公司_无锡网络公司_网站制作 | 达利园物流科技集团-| 博医通医疗器械互联网供应链服务平台_博医通| 设定时间记录电子秤-自动累计储存电子秤-昆山巨天仪器设备有限公司 | 长城人品牌官网|