QStyledItemDelegate類的使用

之前在開發項目的時候遇到一個問題,如下圖所示:


我在ui界面上設置了這個ComboBox的item的CSS樣式之後,但是在調試的時候,總是沒有效果。於是,自己翻看幫助文檔。如果不使用QML的話, 只能使用QStyledItemDelegate這個類來修改item的樣式。

幫助文檔對QStyledItemDelegate類的描述:

The QStyledItemDelegate class provides display and editing facilities for data items from a model.

When displaying data from models in Qt item views, e.g., a QTableView, the individual items are drawn by a delegate. Also, when an item is edited, it provides an editor widget, which is placed on top of the item view while editing takes place. QStyledItemDelegate is the default delegate for all Qt item views, and is installed upon them when they are created.

The QStyledItemDelegate class is one of the Model/View Classes and is part of Qt's model/view framework. The delegate allows the display and editing of items to be developed independently from the model and view.

The data of items in models are assigned an ItemDataRole; each item can store a QVariant for each role. QStyledItemDelegate implements display and editing for the most common datatypes expected by users, including booleans, integers, and strings.

翻譯:

QStyledItemDelegate 這個類提供了顯示和編輯items數據的模型。

在Qt的項目視圖顯示數據時,個人數據是通過代理來描繪出來的,例如QTableView.當一個item被編輯的時候,它提供了一個控件,這個控件代替了你正在編輯的這個區域。QStyledItemDelegate這個類是所有Qt的item視圖的默認代理,同時也是在控件被創建的時候默認的安裝上的。

QStyledItemDelegate類是Qt模型/視圖框架的一部分。它允許開發人員使用自己開發的模型/視圖來顯示和編輯items.

items是通過ItemDataRole來進行分發的。每一個item能夠存儲QVariant中的所有角色。QStyledItemDelegate 類實現了數據被用戶所期望的顯示與編輯樣式,包括布爾類型,整型,字符串等等。

所以經過我的理解,我認爲,這個QStyledItemDelegate是一個樣式的代理類。它可以將你寫好的樣式直接顯示出來。

Delegate  類
概念 與MVC模式不同,model/view結構沒有用於與用戶交互的完全獨立的組件。一般來講, view負責把數據展示給用戶,也處理用戶的輸入。爲了獲得更多的靈性性,交互通過delegagte執行。它既提供輸入功能又負責渲染view中的每個數據項。 
使用Delegate的原因  Qt中當用到QTreeView和QTableView等用於顯示item的視圖時,你要編輯一個item用到的編輯工具可能是除了默認文字編輯lineEdit以外的工具,例如button,spinBox,甚至Slider,ProgressBar,也有可能是自定義的widget。所以Qt提供了一個委託類,用來處理View中的數據展示方式。

Delegate類的繼承架構見下圖:


自從Qt4.4,出現了兩個delegate基類,QStyledItemDelegate vs. QItemDelegate。默認的delegate是QStyledItemDelegate,即你不自己寫delegate的時候,默認那個lineEdit是來自QStyledItemDelegate。Qt Assistant建議用戶如果自定義delegate或者用到了Qt style sheets的話,最好繼承自QStyledItemDelegate,爲什麼呢?首先這兩個類在繪製代理和爲item提供編輯器上面是獨立的,沒什麼聯繫,互不影響;不同的是QStyledItemDelegate使用當前style來繪製item(的代理),即如果程序設置了總體的風格(用QSS或其他定義方式),QStyledItemDelegate會使用這個風格設置。


先看看Qt Demos看了裏面spinboxDelegat的例子:
1. 自定義的delegate繼承自QItemDelegate。


2. 必須重載的一些函數:
       (1)  QWidget *createEditor(QWidget *parent, const QStyleOptionViewItem &option,const QModelIndex &index) const;
       (2)  void setEditorData(QWidget *editor, const QModelIndex &index) const;
       (3)  void setModelData(QWidget *editor, QAbstractItemModel *model,const QModelIndex &index) const;
       (4)  void updateEditorGeometry(QWidget *editor,const QStyleOptionViewItem &option, const QModelIndex &index) const;


3. createEditor創建自定義widget並返回之。
        setEditorData是將model中當前有的數據設置到代理上。自己從model取出數據,自己setValue到editor上。
        setModelData是將editor上的數據保存到Model中。
        updateEditorGeometry就是將editor設置到一定位置,並且有一定大小,使這個editor看起來像是正好嵌入到格子裏面一樣。用的是option.rect。


4. closeEditor() signal 表明用戶完成編輯數據,編輯控件可以銷燬。


5. commitData() signal 必須在完成編輯數據之後,發送該信號,將會把新數據寫回Model


6. paint() and sizeHint(), QitemDelegate默認繼承了該方法,如果需要特殊風格繪製單元項中內容,還需重載這兩個函數。

我們知道,在經典的 MVC 模型中,view用於向用戶展示 model 的數據。但是,Qt提供的不是 MVC 三層架構,而是一個 model/view 設計。這種設計並沒有包含一個完整而獨立的組件用於管理用戶的交互。一般來說,view僅僅是用作對model數據的展示和對用戶輸入的處理,而不應該去做其他的工作。在這種結構中,爲了獲得對用戶輸入控制的靈活性,這種交互工作交給了delegate,也就是“委託”,去完成。簡單來說,就像它們的名字一樣,view 將用戶輸入委託給 delegate 處理,而自己不去處理這種輸入。這些組件提供一種輸入能力,並且能夠在某些 view 中提供這種交互情形下的渲染,比如在 table 中通過雙擊單元格即可編輯內容等。對這種控制委託的標準接口被定義在 QAbstractItemDelegate 類中。
 
delegate 可以用於渲染內容,這是通過 paint() 和 sizeHint() 函數來完成的。但是,對於一些簡單的基於組件的delegate,可以通過繼承 QItemDelegate 或者 QStyledItemDelegate 來實現。這樣就可以避免要完全重寫 QAbstractItemDelegate 中所需要的所有函數。對於一些相對比較通用的函數,在這兩個類中已經有了一個默認的實現。
 
Qt提供的標準組件使用 QItemDelegate 提供編輯功能的支持。這種默認的實現被用在 QListView,QTableView 和 QTreeView 之中。view 實用的delegate可以通過 itemDelegate() 函數獲得。setItemDelegate() 函數則可以爲一個標準組件設置自定義的 delegate。
 
Qt 4.4版本之後提供了兩個可以被繼承的delegate類:QItemDelegate 和 QStyledItemDelegate。默認的delegate是 QStyledItemDelegate。這兩個類可以被相互替代,用於給view 組件提供繪製和編輯的功能。它們之間的主要區別在於,QStyledItemDelegate 使用當前的風格(style)去繪製組件。所以,在自定義delegate或者需要使用 Qt style sheets 時,建議使用 QStyledItemDelegate 作爲父類。使用這兩個類的代碼通常是一樣的,除了需要使用style進行繪製的部份。如果你希望爲view item自定義繪製函數,最好實現一個自定義的style。這個你可以通過QStyle類來實現。
 
如果delegate沒有支持爲你的數據類型進行繪製,或者你希望自己繪製item,那麼就可以繼承 QStyledItemDelegate 類,並且重寫 paint() 或者還需要重寫 sizeHint() 函數。paint() 函數會被每一個item獨立調用,而sizeHint()函數則可以定義每一個item 的大小。在重寫 paint() 函數的時候,通常需要用 if 語句找到你需要進行渲染的數據類型並進行繪製,其他的數據類型需要調用父類的實現進行繪製。
 
一個自定義的delegate也可以直接提供一個編輯器,而不是使用內置的編輯器工廠(editor item factory)。如果你需要這種功能,那麼需要實現一下幾個函數:
createEditor(): 返回修改數據的組件;
setEditorData(): 爲editor提供編輯的原始數據;
updateEditorGeometry(): 保證editor顯示在 item view 的合適位置以及大小;
setModelData(): 根據editor 的數據更新model的數據。

所以,之前的問題解決了,我在ui界面進行構造的時候增加了這幾行代碼:

    itemDelegate = new QStyledItemDelegate();
    ui->platComboBox->setItemDelegate(itemDelegate);
    ui->methodComboBox->setItemDelegate(itemDelegate);

然後效果就能顯示出來了。




發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章