当数据发生变化时,如何强制模型更新QComboBox



我为QComboBox:创建了模型

#ifndef QCOMBOBOXMODEL_H
#define QCOMBOBOXMODEL_H
#include <QModelIndex>

class QComboBoxModel : public QAbstractListModel
{
public:
QComboBoxModel(QObject *parent=nullptr);
int rowCount(const QModelIndex &) const;
QVariant data(const QModelIndex &index, int role) const;
void populate(const QList<QPair<int,QString>> &values);
private:
QList<QPair<int,QString>> values;
};
#endif // QCOMBOBOXMODEL_H

代码

#include "qcomboboxmodel.h"
#include <QModelIndex>
QComboBoxModel::QComboBoxModel(QObject *parent)
:QAbstractListModel(parent)
{
}
int QComboBoxModel::rowCount(const QModelIndex &) const
{
return values.count();
}

QVariant QComboBoxModel::data( const QModelIndex &index, int role ) const
{        
QVariant value;
switch ( role )
{
case Qt::DisplayRole: //string
{
value = this->values.value(index.row()).second;
}
break;
case Qt::UserRole: //data
{
value = this->values.value(index.row()).first;
}
break;
default:
break;
}
return value;
}
void QComboBoxModel::populate(const QList<QPair<int,QString>> &values)
{
this->values = values;
}

现在我用

values.append(QPair<int,QString>(-1,"Select item"));
values.append(QPair<int,QString>(10,"item1(0)"));
values.append(QPair<int,QString>(11,"item1(1)"));
values.append(QPair<int,QString>(21,"item1(2)"));
values.append(QPair<int,QString>(32,"item1(3)"));
values.append(QPair<int,QString>(44,"item1(4)"));
newidx = 50;

model = new QComboBoxModel();
model->populate(values);
this->ui->comboBox->setModel(model);

点击按钮,我将新项目添加到组合框

newidx++;
QString strIdx = QString().number(newidx);
values.append(QPair<int,QString>(newidx,"New item("+strIdx+")"));
model = new QComboBoxModel();
model->populate(values);
this->ui->comboBox->setModel(model);

这一切似乎都很好,但这里的问题是,每次我向组合框数据添加新项目时,我都需要重新创建模型

model = new QComboBoxModel();
model->populate(values);
this->ui->comboBox->setModel(model);

这样做合适吗?或者还有其他方法可以在数据更新时强制模型更新组合框?

根据"模型子类引用";在文档中,要制作一个可编辑的模型,还需要做更多的工作。你为什么不使用像QStandardItemModel这样现成的模型?

comboModel = new QStandardItemModel(0, 2, this);
ui->comboBox1->setModel(comboModel);
comboModel->insertRow(0);
comboModel->setData(comboModel->index(0, 0), -1);
comboModel->setData(comboModel->index(0, 1), "Select item");
//and so on
//and the data is available as
int number = comboModel->data(comboModel->index(0, 0)).toInt();
QString itemtext = comboModel->data(comboModel->index(0, 1)).toString();

我找到了解决方案!

首先,我为模型添加了新方法

void QComboBoxModel::append(int index, QString value)
{
int newRow = this->values.count();
this->beginInsertRows(QModelIndex(), newRow, newRow);
values.append(QPair<int,QString>(index,value));
endInsertRows();
}

现在点击按钮的方法改为这个

void MainWindow::on_pushButton_clicked()
{
qDebug() << "Clicked!";
newidx++;
QString strIdx = QString().number(newidx);
model->append(newidx,"new item " + strIdx );
}

重点是使用beginInsertRowsendInsertRows通知模型数据实际发生了变化!

现在一切如愿以偿!

现在,您还可以修改append方法来向其批量添加行,但我认为,若您添加了许多行,最好只是重新创建模型并将其重新分配给combobox。

更新1:

还要记住,您在模型内部更新valuesQList,所以如果您添加

qDebug() << values;

on_pushButton_clicked()方法中,您总是看到

(QPair(-1,"Select item"), QPair(10,"item1(0)"), QPair(11,"item1(1)"), QPair(21,"item1(2)"), QPair(32,"item1(3)"), QPair(44,"item1(4)"))

更新2:

我还更新了populate方法

void QComboBoxModel::populate(const QList<QPair<int,QString>> &newValues)
{
int oldIdx = this->values.count();
int newIdx = newValues.count();
this->beginInsertRows(QModelIndex(), oldIdx, newIdx);
this->values = newValues;
endInsertRows();
}

现在您可以使用values列表

void MainWindow::on_pushButton_clicked()
{
qDebug() << "Clicked!";
newidx++;
QString strIdx = QString().number(newidx);
values.append(QPair<int,QString>(newidx,"new item " + strIdx));
model->populate(values);
qDebug() << values;
}

更新3:

现在,我发现了一个大问题——我没有在模型内部使用指针,所以当我将QList传递给模型时,它只是创建副本,而不是使用已经创建的,所以我重写了模型和其他代码:

型号

#ifndef QCOMBOBOXMODEL_H
#define QCOMBOBOXMODEL_H
#include <QModelIndex>

class QComboBoxModel : public QAbstractListModel
{
public:
QComboBoxModel(QObject *parent=nullptr);
int rowCount(const QModelIndex &) const;
QVariant data(const QModelIndex &index, int role) const;
void populate(QList<QPair<int,QString>> *newValues);
void append(int index, QString value);
private:
QList<QPair<int,QString>> *values;
};
#endif // QCOMBOBOXMODEL_H
#include "qcomboboxmodel.h"
#include <QModelIndex>
#include <QDebug>
QComboBoxModel::QComboBoxModel(QObject *parent)
:QAbstractListModel(parent)
{
values = new QList<QPair<int,QString>>();
}
int QComboBoxModel::rowCount(const QModelIndex &) const
{
return values->count();
}

QVariant QComboBoxModel::data( const QModelIndex &index, int role ) const
{        
QVariant value;
switch ( role )
{
case Qt::DisplayRole: //string
{
value = this->values->value(index.row()).second;
}
break;
case Qt::UserRole: //data
{
value = this->values->value(index.row()).first;
}
break;
default:
break;
}
return value;
}
void QComboBoxModel::populate(QList<QPair<int,QString>> *newValues)
{
int oldIdx = this->values->count();
int newIdx = newValues->count();
this->beginInsertRows(QModelIndex(), oldIdx, newIdx);
this->values = newValues;
endInsertRows();
}
void QComboBoxModel::append(int index, QString value)
{
int newRow = this->values->count();
this->beginInsertRows(QModelIndex(), newRow, newRow);
values->append(QPair<int,QString>(index,value));
endInsertRows();
}

主要形式

#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include "qcomboboxmodel.h"
#include <QMainWindow>
QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
QT_END_NAMESPACE
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
MainWindow(QWidget *parent = nullptr);
~MainWindow();
private slots:
void on_comboBox_currentIndexChanged(int index);
void on_comboBox_currentIndexChanged(const QString &arg1);
void on_pushButton_clicked();
private:
Ui::MainWindow *ui;
int newidx;
QList<QPair<int,QString>> *values;
QComboBoxModel *model;
};
#endif // MAINWINDOW_H
#include "mainwindow.h"
#include "qcomboboxmodel.h"
#include "ui_mainwindow.h"
#include <QDebug>
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::MainWindow)
{
ui->setupUi(this);
values = new QList<QPair<int,QString>>();
values->append(QPair<int,QString>(-1,"Select item"));
values->append(QPair<int,QString>(10,"item1(0)"));
values->append(QPair<int,QString>(11,"item1(1)"));
values->append(QPair<int,QString>(21,"item1(2)"));
values->append(QPair<int,QString>(32,"item1(3)"));
values->append(QPair<int,QString>(44,"item1(4)"));
newidx = 50;

model = new QComboBoxModel();
model->populate(values);
this->ui->comboBox->setModel(model);
}
MainWindow::~MainWindow()
{
delete ui;
}

void MainWindow::on_comboBox_currentIndexChanged(int index)
{
qDebug() << ui->comboBox->itemData(index).value<int>();
}
void MainWindow::on_comboBox_currentIndexChanged(const QString &arg1)
{
qDebug() << arg1;
}
void MainWindow::on_pushButton_clicked()
{
qDebug() << "Clicked!";
newidx++;
QString strIdx = QString().number(newidx);
values->append(QPair<int,QString>(newidx,"new item " + strIdx));
model->populate(values);
qDebug() << values->toStdList();
}

现在一切看起来都很好,并按预期工作!

为什么不通过"QAbstractItemModel*model((const";来自QComboBox;改变它并再次分配它(通过"void QComboBox::setModel(QAbstractItemModel*model("(?

相关内容

  • 没有找到相关文章

最新更新