久久久久久久av_日韩在线中文_看一级毛片视频_日本精品二区_成人深夜福利视频_武道仙尊动漫在线观看

Qt 5.2 Model-View-Pattern:如何通知模型對象底層數據結

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

問題描述

我有一個類用于永久存儲一些以表格方式組織的項目.這個類與 Qt 完全無關,來自不同的庫.對于這個問題的其余部分,讓我們調用這個類 DataContainer.它提供了與 std-c++ 兼容的迭代器來訪問和操作內容.

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 顯示和修改該數據.我的想法是創建一個類 DataContainerQtAdaptor,它繼承自 QAbstractTableModel 并存儲一個指向 DataContainer 對象的指針.DataContainerQtAdaptor 用作 DataContainer 對象的適配器,我的 Qt 應用程序內部的所有操作都通過此適配器完成.然后我使用 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 可能會被線程/進程更改.(例如,將 DataContainer 視為封裝數據庫連接的某個 C++ 類,并且該數據庫可能會被其他人更改.)

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) 假設我有一個函數,每次 DataContainer 對象的內部結構發生變化時都會調用該函數.必須調用 QAbstractTableModel 來通知模型底層更改的正確函數是什么?我需要類似親愛的模型,您的持久存儲后端已更改.請更新自己并向每個附加視圖發出信號以反映此更改".

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) 假設 1) 已解決.如果更改是通過 GUI 觸發的,那么避免雙重"GUI 更新的最佳方法是什么?例如:用戶單擊表格小部件中的單元格 -> 表格小部件調用模型的 setData -> 模型將更改推送到后端 -> 后端觸發其自己的onUpdate"功能 -> 模型重新讀取完整的后端(盡管它已經知道更改)-> 第二次更新 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) 用戶應該能夠通過 GUI 插入新的行/列并將數據放入其中.但是位置是由這個數據決定的,因為后端保持數據的排序.因此,我有以下問題:用戶決定在最后創建一個新行,并將新數據推送到后端.當重新讀取后端/模型時,此數據通常不在最后位置,而是已插入中間某處,并且所有其他數據已向前移動.我如何保持表格視圖小部件的所有屬性(如選擇單元格")同步?

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?

我相信,對于所有這些問題,一定有一些簡單的標準解決方案,因為它與 QFileSystemModel 的工作方式相同.用戶選擇一個文件,其他一些進程創建一個新文件.新文件顯示在視圖中,所有后續行向前移動.選擇也向前推進.

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.

馬蒂亞斯

推薦答案

模型語義

首先要保證QAbstractItemModel不能處于不一致的狀態.這意味著必須在模型上觸發一些信號, 在對基礎數據進行某些更改之前.

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.

結構更改和數據更改之間存在根本區別.結構更改是添加或刪除模型的行/列.數據更改僅影響現有數據項的值.

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.

  • 結構更改需要在修改前后調用 beginXxxendXxx.在調用 beginXxx 之前,您不能修改任何結構.完成結構更改后,調用 endXxx.Xxx 是以下之一:InsertColumns、MoveColumns、RemoveColumnsInsertRows、MoveRows、RemoveRows、ResetModel.

  • 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.

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

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.

保持結構完整的數據更改只需要在修改基礎數據之后發送dataChanged.這意味著在查詢模型的對象接收到 dataChanged 之前,對 data 的調用可能會返回一個新值.

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 類中的非常量模型幾乎沒有用,除非您當然使用觀察者或類似模式實現橋接功能.

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.

處理模型更新循環的 Qt 慣用方法是利用項目角色.模型如何解釋角色完全取決于您.QStringListModel 實現的一個簡單而有用的行為是將角色從 setData 調用轉發到 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.

股票視圖小部件僅對帶有 DisplayRoledataChanged 做出反應.然而,當他們編輯數據時,他們使用 EditRole 調用 setData.這打破了循環.該方法既適用于查看小部件,也適用于 Qt 快速查看項目.

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.

只要模型在排序完成時正確地發出變化信號,你就會沒事.

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

操作順序為:

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

  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.

編輯從行中的一個項目開始.視圖狀態更改為 Editing.

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

對項目進行編輯.視圖退出編輯狀態,并在模型上設置數據.

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

模型根據項目的內容確定項目的最終位置.

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

模型調用beginMoveRows.

模型通過在正確的位置插入項目來改變容器.

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

模型調用endMoveRows.

此時,一切都如您所愿.如果在移動之前獲得焦點,則視圖可以自動跟隨移動的項目.默認情況下,編輯的項目具有焦點,因此效果很好.

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 沒有足夠的功能使其工作除非對它的所有訪問都通過模型完成.如果你想直接訪問容器,要么讓容器顯式繼承QAbstractXxxxModel,要么你必須給容器添加一個通知系統.前者是更簡單的選擇.

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.

您的核心問題簡化為:我能否在不實現模型通知 API 的某些變體的情況下擁有模型功能.顯而易見的答案是:不,對不起,你不能——根據定義.要么功能存在,要么不存在.如果您不希望容器成為 QObject,您可以使用觀察者模式實現通知 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 由文件系統通知有關已更改的單個目錄條目.你的容器也必須這樣做——這相當于以某種形狀或形式提供一個 dataChanged 信號.如果模型有被移動或添加/刪除的項目 - 它的結構發生了變化 - 它必須通過調用相關的 beginZzz 來發出 xxxAboutToBeYyyxxxYyy 信號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 最重要的未記錄方面是:它的實例僅在模型結構沒有改變時才有效.如果您的模型傳遞了在結構更改之前生成的索引,您就可以自由地以未定義的方式行事(崩潰、發動核打擊等).

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() 存在的全部原因是您擁有一個基礎的、復雜索引的數據容器的用例.模型的 createIndex 方法的實現必須生成索引實例,以某種形式存儲對 DataContainer 索引的引用.如果這些索引適合指針,則不需要在堆上分配數據.如果需要在堆上分配容器索引存儲,則必須保留指向此數據的指針,并在容器結構發生變化時將其刪除.您可以隨意執行此操作,因為在結構更改后沒有人應該使用索引實例.

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.

這篇關于Qt 5.2 Model-View-Pattern:如何通知模型對象底層數據結構的變化的文章就介紹到這了,希望我們推薦的答案對大家有所幫助,也希望大家多多支持html5模板網!

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

相關文檔推薦

How can I read and manipulate CSV file data in C++?(如何在 C++ 中讀取和操作 CSV 文件數據?)
In C++ why can#39;t I write a for() loop like this: for( int i = 1, double i2 = 0; (在 C++ 中,為什么我不能像這樣編寫 for() 循環: for( int i = 1, double i2 = 0;)
How does OpenMP handle nested loops?(OpenMP 如何處理嵌套循環?)
Reusing thread in loop c++(在循環 C++ 中重用線程)
Precise thread sleep needed. Max 1ms error(需要精確的線程睡眠.最大 1ms 誤差)
Is there ever a need for a quot;do {...} while ( )quot; loop?(是否需要“do {...} while ()?環形?)
主站蜘蛛池模板: 九九爱这里只有精品 | 欧美激情在线精品一区二区三区 | 久久精品在线 | 国产精品久久久久久久久久久久 | 精品国产第一区二区三区 | 亚洲bt 欧美bt 日本bt | 婷婷激情综合 | 天天操人人干 | 国产精品成人一区二区 | 黄色毛片黄色毛片 | 草草影院ccyy | 欧美日韩久久久久 | 久久精品屋 | 亚洲欧美在线一区 | 99久9| 国产网站在线免费观看 | 欧美日韩一区在线 | 免费在线一区二区 | 亚洲国产精品一区二区第一页 | 国产一区二区三区 | 狠狠狠干 | 一级aaaaaa毛片免费同男同女 | 久久伊人影院 | 国产电影一区二区在线观看 | 日韩午夜电影 | 日韩欧美在线免费观看 | 国产精品久久久亚洲 | 伊人青青久久 | 亚洲一二三在线 | 在线视频中文字幕 | 国产91一区二区三区 | 久久毛片网站 | 在线黄色影院 | 久久99精品久久久97夜夜嗨 | 日韩av在线一区 | 欧美黑人狂野猛交老妇 | 成人1区2区 | 欧美日韩高清在线一区 | 爱爱综合网 | 超碰成人在线观看 | 国产毛片av |