Qt:带有QAbstractItemModel和QStyledItemDelegate的QListView需要很长时间才能添加项

时间:2018-01-18 19:57:10

标签: c++ qt qlistview qabstractitemmodel qstyleditemdelegate

我有一个带有QListView的qt应用程序,一个自定义模型和一个继承自QStyledItemDelegate的类来显示自定义项目。不幸的是,当我添加大约6000个项目时需要很长时间(5秒)。你对我的问题有一个提示/解决方案吗?

下面你看我的实施:

型号:

class AddressItemData : public QObject {
    Q_OBJECT

public:
    AddressItemData (QObject * parent = 0) : QObject(parent) {}

    QString address;
    QString name;
    bool inserted;
};

class AddressModel : public QAbstractListModel
{
    Q_OBJECT
public:
    AddressModel (QObject *parent = 0);

    int rowCount(const QModelIndex &parent = QModelIndex()) const {
       return addressItems.count();
    }

    QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const {
       if (!index.isValid())
           return QVariant();

       if (index.row() >= addressItems.size() || index.row() < 0)
           return QVariant();

       if (Qt::DisplayRole == role) {
           return QVariant::fromValue<AddressItemData*>(addressItems.at(index.row()));
       }

       return QVariant();
   }

    void addAddressItem(AddressItemData* addressItem){
       beginInsertRows(QModelIndex(), rowCount(), rowCount());
       addressItems.append(addressItem);
       endInsertRows();
    }

    void addAddressItems(QList<AddressItemData*> addressItems){
       beginInsertRows(QModelIndex(), rowCount(), rowCount() + addressItems.size() - 1);
       this->addressItems.append(addressItems);
       endInsertRows();
    }

    void removeAddressItem(AddressItemData* addressItem);

    void deleteAllAddressItems(void){
       beginRemoveRows(QModelIndex(), rowCount(), rowCount());
       for (int i = 0; i < addressItems.size(); ++i) {
           delete addressItems.at(i);
       }
       addressItems.clear();
       endRemoveRows();
    }


private:
    QList<AddressItemData*> addressItems;

};

对于模型,我创建了一个自定义的添加和删除方法,该方法将从委托中调用。

ItemViewDelegate:

class AddressViewDelegate : public QStyledItemDelegate
{
    Q_OBJECT
public:
    AddressViewDelegate (QWidget *parent = 0) : QStyledItemDelegate(parent) {}

    void paint(QPainter *painter, const QStyleOptionViewItem &option,
                const QModelIndex &index) const {

        if(!index.isValid())
             return;

        painter->save();

        QStyleOptionViewItemV4 opt = option;

        if (option.state & QStyle::State_Selected)
             painter->fillRect(option.rect, option.palette.highlight());

        QRect addressRect = opt.rect;

        AddressItemData* d = index.data().value<AddressItemData*>();

        painter->setPen(Qt::black);
        painter->drawText(QRect(addressRect.left(), addressRect.top(),  addressRect.width(), addressRect.height()/2),
                       opt.displayAlignment,  d->address);
   }

    QSize sizeHint(const QStyleOptionViewItem &option,
                    const QModelIndex &index) const {
        if(!index.isValid())
             return QSize();

        QSize result = QStyledItemDelegate::sizeHint(option, index);
        result.setHeight(result.height()*2);

        return result;
   }
};

出于测试目的,应用程序仅显示地址。我想在一行中显示地址旁边的其他信息。后来我还想为每一行添加信号/插槽行为,但这还有很长的路要走。

主要:

AddressModel* model = new AddressModel;
AddressViewDelegate* viewDelegate = new AddressViewDelegate;
ui->listView->setItemDelegate(viewDelegate);
ui->listView->setModel(model);
ui->listView->setUniformItemSizes(true);
ui->listView->setLayoutMode(QListView::Batched);

QList<AddressItemData *> addressItems;
... for loop to add AddressItemData:
    AddressItemData* data = new AddressItemData;
    data->address = anotherTable.at(index);
    addressItems.append(data);
// ...

model->addAddressItems(addressItems);

main中,我调用了addAddressItems,但是对于单调用变量,它也很慢。我希望我的代码足够清晰,我也可以帮助其他人。

你有一个想法,为什么添加程序太慢了?

0 个答案:

没有答案