У меня есть собственное хранилище, и я хочу реализовать ListModel
, чтобы отобразить его с помощью QComboBox
. Для простоты предположим, что у нас есть список int
в качестве данных по типовому, так вот моя реализация модели и программы испытаний:QComboBox с пользовательской моделью
#include <QApplication>
#include <QDebug>
#include <QAbstractListModel>
#include <QComboBox>
#include <QHBoxLayout>
#include <QPushButton>
QList<int> list;
class MyModel : public QAbstractListModel
{
public:
MyModel(QWidget* parent):
QAbstractListModel(parent)
{}
~MyModel()
{
qDebug() << __FUNCTION__;
}
QVariant data(const QModelIndex &index, int role) const
{
if (!index.isValid())
return QVariant();
if ((role == Qt::DisplayRole) && (index.row() < list.size()))
return QString::number(list.at(index.row()));
return QVariant();
}
int rowCount(const QModelIndex &parent) const
{
Q_UNUSED(parent)
return list.size();
}
};
int main (int argc, char* argv[])
{
QApplication app (argc, argv);
QWidget w;
QHBoxLayout* l = new QHBoxLayout();
QComboBox* c = new QComboBox(&w);
c->setModel(new MyModel(c));
l->addWidget(c);
QPushButton* b = new QPushButton("+");
QObject::connect(b, &QPushButton::clicked, [](){
list.push_back(qrand());
qDebug() << list;
});
l->addWidget(b);
b = new QPushButton("-");
QObject::connect(b, &QPushButton::clicked, [](){
if (!list.isEmpty())
list.pop_back();
qDebug() << list;
});
l->addWidget(b);
w.setLayout(l);
w.show();
return app.exec();
}
Если я ударил кнопку Добавить только один раз, а затем проверить список, его выглядит нормально, но когда я снова ударил его, QComboBox
отображает только первое значение и пустую строку; продолжение добавления новых элементов не влияет на QComboBox
. Если я нажимаю на кнопку , добавьте много раз, затем я вижу правильный список в ComboBox
.
Я не могу понять, что происходит и что я делаю неправильно.
Я использую Qt5.5.1
с VS2013 x32
по адресу Windows 7
.
Спасибо за отличное объяснение! Но единственная проблема, которая приведена в моем примере, - это упрощение реальной ситуации, и она не может быть инкапсулирована в модель, потому что она уже инкапсулирована другим классом :-(Есть ли какой-либо другой способ для изменения модели извне? – Jeka
Если вы не можете вызывать функции-члены MyModel прямо до и после изменения данных, тогда это невозможно. Вы должны изменить свой дизайн программы, чтобы класс модели отвечал за обработку данных, либо установив свой другой класс в качестве члена MyModel , или с помощью множественного наследования в вашем другом классе. Архитектура модели не волшебна, она не может обнаружить изменение контента в простом контейнере памяти. – galinette