在QT4中使用QTableView製作屬性編輯器

來源:互聯網
上載者:User
最近在用QT寫的一個程式中,需要一個對大量參數進行設定的功能。過去用Delphi的經驗是,盡量不要使用QListView和TGrid來實現,因為涉及到控制項的對齊,介面的重繪等,反而使簡單問題變得複雜。因此這次用QT寫程式時也想當然,用控制項數組的方式來解決。很快程式寫好了,介面如下:

顯示出的效果還不錯,但是遇到了一個嚴重的問題,那就是速度。由於QT的機制是自動調整控制項比例來適應各種系統和表單大小,而這個調整的功能其實涉及到複雜的運算。另外,QT的控制項建立也不如真正控制項的建立那麼快。因此當控制項數量一大,構建整個介面就變得其慢無比了。在我的機器上,像這樣的介面開啟需要1-2秒時間,而且即使到了效能較好的電腦上也沒有什麼大的改善。這樣的效果就連自己都無法忍受,更別說使用者了。

於是考慮改進,參考QT的example中的spinboxdelegate例子,使用QTableView來解決。具體方法是:

1)在控制項設計器中放置一個QTableView,並調整好其與其它控制項的位置關係。產生ui檔案,在程式中製作相應的介面表單類。

2)從QItemDelegate中繼承出一個新的類,它將用來配合上面的QTableView,用來告訴其是否可以針對某個Cell進入編輯模式,以及在編輯該Cell時,使用什麼控制項,相互的值如何傳遞等。
具體來說,只要繼承QItemDelegate中以下的幾個虛函數就可以了:

class enstCatheterNodeInfoDelegate : public QItemDelegate
{
    Q_OBJECT
public:
    enstCatheterNodeInfoDelegate(QObject *parent, enstCatheterInfo *pCatheterInfo);
    QWidget* createEditor(QWidget *parent, const QStyleOptionViewItem &option,
                const QModelIndex &index) const;
    void setEditorData(QWidget *editor, const QModelIndex &index) const;
    void setModelData(QWidget *editor, QAbstractItemModel *model,
                const QModelIndex &index) const;
    void updateEditorGeometry(QWidget *editor, const QStyleOptionViewItem &option,
                const QModelIndex &index) const;
};

createEditor()函數,在QTableView中某個Cell被DoubleClick時觸發,這時可以用其index參數,獲得該Cell的行與列,如果確定該Cell是可以被編輯的,那麼就產生一個對應的編輯控制項,如:

            QComboBox *cbo = new QComboBox(parent);
            cbo->addItem(" 1 ");
            cbo->addItem(" 2 ");
            cbo->addItem(" 3 ");
            cbo->installEventFilter(const_cast<enstCatheterNodeInfoDelegate*>(this));
            return cbo;

這時,一個ComboBox就會被自動替換到該Cell的位置上了。以上cbo->installEventFilter(),是為了讓QItemDelegate能夠獲得使用者在該控制項上的Enter,Escape等事件,以便做出相應處理。
如果該Cell不能被編輯,此時返回NULL就可以了。

setEditorData()函數,用來對產生的控制項中的值進行初始化,一般來說,這個函數在以上的createEditor()函數結束後會被自動調用,如下:

            QComboBox *cbo = static_cast<QComboBox*>(editor);
            cbo->setCurrentIndex(0);

editor是QWidget類型的參數,它代表createEditor()函數中產生的那個控制項,這裡必須將其進行類型轉換,才可以變成自己實際產生的那個控制項類型。如果在createEditor()中根據index.column()不同,產生了不同的編輯控制項,那麼這裡也需要判斷index.column(),來將editor參數轉換成相應的控制項。

接著setModelData(),它會在使用者的離開當前編輯中的Cell時被調用,可以在此將編輯控制項中被修改了的資料寫回到QTableView中,如下:

            QString tmpstr;
            QComboBox *cbo = static_cast<QComboBox*>(editor);
            tmpstr.setNum(cbo->currentIndex());
            model->setData(index, tmpstr);

最後,updateEditorGeometry(),這個函數是用來控制編輯控制項的位置的,一般只需要寫成:

    editor->setGeometry(option.rect);

編輯控制項就會自動被調整到Cell的大小了。

3)在實際的表單類中,使用如下的代碼將以上這個類與QTableView關聯起來:

    enstCatheterNodeInfoDelegate *delegate = new enstCatheterNodeInfoDelegate(this);
    tbl1->setItemDelegate(delegate);

4)光這樣還不行,由於QTableView實在太底層了,它還需要知道以怎樣的方式顯示,即指定一個ItemModel,可以選用的類包括:
QDirModel:可以以樹狀方式顯示某個目錄下的所有子目錄,以及其相關資訊。
QProxyModel:用來將舊的Model類型過渡到新類型上的。
QStandardItemModel:最簡單的Grid方式的顯示Model。
另外,還可以自己從QAbstractListModel, QAbstractProxyModel, QAbstractTableModel來繼承出符合自己要求的model。
偷個懶,我就直接使用QStandardItemModel了:

    mItemModel = new QStandradItemMode(this, 3, 10);
    tbl1->setModel(mItemModel);

5)基本完成,最後再加上初始化QTableView中所有文字,以及最終將設定好了的內容儲存出來的代碼,就可以了,完成的介面顯示如下:

但是,仔細看看,還有不少不滿意的地方,TableView的ColumnHeader居然自動填上了數字,而左邊則多出了一條垂直Header,另外,所有Cell的寬度變成一樣的了,多少有點不爽。。經過努力,總算摸索出瞭解決方法,不過不清楚真正的解決方案是什麼,我這個解決方案應該並不好:

首先從QStandardItemModel中繼承出自己的類,暫且名叫enstCatheterNodeItemModel了:

class enstCatheterNodeItemModel : public QStandardItemModel
{
    Q_OBJECT
public:
    enstCatheterNodeItemModel(QObject *parent = 0);
};

在其建構函式中,使用:

enstCatheterNodeItemModel::enstCatheterNodeItemModel(QObject *parent)
    : QStandardItemModel(MAX_CATHETERNODE_COUNT, 3, parent)
{
    setHeaderData(0, Qt::Horizontal, tr("Input"));
    setHeaderData(1, Qt::Horizontal, tr("Signal"));
    setHeaderData(2, Qt::Horizontal, tr("Locate"));
}

強制其只能有三列,並指定每個列的標題。

在表單的建構函式中,進一步調整QTableView:

    QHeaderView *header;
    header = tbl1->horizontalHeader();
    header->resizeSection(0, 260);
    header->resizeSection(1, 260);
    header->resizeSection(2, 50);
    header = tbl1->verticalHeader();
    header->hide();

設定其各個列的寬度,同時將左邊的垂直Header隱藏。

總算大功告成,載入延時已經基本感覺不到了。看看最後的效果:

以及另一組編輯器,其中的顏色選擇ComboBox並不是QT內建的控制項,而是自己實現的,照樣可以被做成編輯控制項:

完。

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.