2014-11-03 93 views
1

我已經實現了自定義QTableViewQAbstractTableModelQTableView使用Qt-缺省文本行編輯委託來處理字符串數據。我想確保在提交編輯(按enter)後,該字符串對於其列是唯一的。如果另一行的值與該列的值相同,則編輯將被拒絕,可能會出現一個彈出框,然後文本行編輯將以編程方式返回到編輯模式,以便用戶再次嘗試。確保QTableView中列的唯一值

我曾考慮過使用自定義委託,並可能通過信號和插槽在委託和表視圖之間進行通信。代表可以確保該值在setModelData()內唯一。要做到這一點,必須注入其他專欄的知識。如果該值不是唯一的,那麼委託可以發出一個表格視圖可以拾取的信號;像notUniqueTryAgain()。在該插槽內,表格會彈出一條消息,然後在該單元上呼叫edit()。這是正確的路嗎?

+0

這取決於你的模型,但我會寫模型中的布爾成員函數,告訴您該數據對於該列是否唯一。爲此,你不需要信號和插槽。將QStyledItemDelegate :: model()轉換爲您的子類模型並直接調用成員函數。儘管數據量很大,但這可能會嚴重影響性能。在這種情況下,您希望通過快速查找將數據保存在某種類型的容器中。例如,std :: unordered_map。 – 2014-11-04 00:09:30

+0

Gotcha。你將如何解決以編程方式將單元放回編輯模式的問題?爲此我相信我們需要訪問QTableView,代表和模型都不知道 – 2014-11-04 00:37:00

+0

這一部分我沒有想到。根據以前,我沒有做過很多用戶可編輯的模型。一個信號/插槽可能工作,或者你可能只是在代表中的同一個函數中使用循環,不是嗎? – 2014-11-05 00:44:27

回答

2

下次使用委託:

#ifndef ITEMDELEGATE_H 
#define ITEMDELEGATE_H 

#include <QItemDelegate> 

class ItemDelegate : public QItemDelegate 
{ 
    Q_OBJECT 
public: 
    explicit ItemDelegate(QObject *parent = 0); 

protected: 
    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; 

signals: 

public slots: 

}; 

#endif // ITEMDELEGATE_H 

.cpp的

#include "itemdelegate.h" 
#include <QLineEdit> 
#include <QDebug> 

ItemDelegate::ItemDelegate(QObject *parent) : 
    QItemDelegate(parent) 
{ 
} 

QWidget *ItemDelegate::createEditor(QWidget *parent, 
            const QStyleOptionViewItem &option, 
            const QModelIndex &index) const 
{ 
    QLineEdit *editor = new QLineEdit(parent); 
    return editor; 
} 


void ItemDelegate::setEditorData(QWidget *editor, 
           const QModelIndex &index) const 
{ 
    QString value =index.model()->data(index, Qt::EditRole).toString(); 
    QLineEdit *line = static_cast<QLineEdit*>(editor); 
    line->setText(value); 
} 


void ItemDelegate::setModelData(QWidget *editor, 
           QAbstractItemModel *model, 
           const QModelIndex &index) const 
{ 
    QLineEdit *line = static_cast<QLineEdit*>(editor); 
    QString data = line->text(); 

    int column = index.column(); 

    for(int i = 0; i < model->rowCount(); i++) 
    { 
     QModelIndex cur = model->index(i,column); 
     qDebug() << data << model->data(cur, Qt::EditRole).toString(); 
     if(data == model->data(cur, Qt::EditRole).toString()) 
     { 
      model->setData(index, "wrong"); 
      return; 
     } 
    } 

    model->setData(index, data); 
} 


void ItemDelegate::updateEditorGeometry(QWidget *editor, 
             const QStyleOptionViewItem &option, 
             const QModelIndex &index) const 
{ 
    editor->setGeometry(option.rect); 
} 

用法:

ItemDelegate *itDelegate = new ItemDelegate; 
ui->tableView->setItemDelegate(itDelegate); 

這是很好的例子,這樣你就可以做所有其他的事情,比如:

if(data == model->data(cur, Qt::EditRole).toString()) 
{ 
    //model->setData(index, "wrong"); 
    QMessageBox msgBox; 
    msgBox.setText("Try again."); 
    msgBox.exec(); 
    return; 
} 

等。

當然,如果有鑑於許多項目,它可能會很慢,所以你可以使用QProgressDialog顯示用戶有多少次你需要:

QProgressDialog progress("Checking...", "Searching", 0, model->rowCount(), 0); 
for(int i = 0; i < model->rowCount(); i++) 
{ 
    progress.setValue(i); 
    QModelIndex cur = model->index(i,column); 
    qDebug() << data << model->data(cur, Qt::EditRole).toString(); 
    if(data == model->data(cur, Qt::EditRole).toString()) 
    { 
     model->setData(index, "wrong"); 
     return; 
    } 
    if (progress.wasCanceled()) 
     return; 
} 
progress.close();