Answer the question
In order to leave comments, you need to log in
How to output information from QVector correctly?
It is required to implement a simple directory. Created a class describing the directory object. I added several instances of the class to QVector and tried to display this in a table, creating a QTableWidgetItem for each field, but in the end, with a non-empty vector, the program with code 3 crashes. So apparently I'm doing something wrong, and the following questions arise:
How to clear widget (or Layout) from all child widgets? (Each time the directory changes, I planned to re-create a new table)
How would you implement changing information output? (Maybe I'm thinking in the wrong direction)
Answer the question
In order to leave comments, you need to log in
Discover Model/View in Qt. In particular, your problem with directories is described here .
In short: you have a model where you bind your storage method ( QVector
in your case) to a standard interface QAbstractItemModel
(or its descendants QAbstractListModel
, QAbstractTableModel
or QAbstractTreeModel
) that can be passed to one of the standard view widgets ( QListView
, QTableView
, QTreeView
). By implementing the interface (overriding the virtual methods for data
both setData
role== Qt::DisplayRole
and Qt::EditRole
), you can simply change the state of the model, and the view widgets will pick up the changes automatically.
In addition, there is also such a thing - QDataWidgetMapper
. He knows how to bind widgets (even ordinary ones, not View ones) to certain fields in the model.
Пример объемный, но минимально полный, содержащий всю необходимую инфраструктуру. Допустим, мы хотим создать редактор для некоторых статей (блога?). Нам нужен простой класс Article
, чтобы собрать в кучу данные о каждой отдельной статье:
class Article
{
public:
Article(int id, const QString& title, const QString& content)
: _id(id), _title(title), _content(content) {}
int id() const { return _id; }
void setId(int id) { _id = id; }
QString title() const { return _title; }
void setTitle(const QString& title) { _title = title; }
QString content() const { return _content; }
void setContent(const QString& content) { _content = content; }
private:
int _id;
QString _title;
QString _content;
};
rowCount
, columnCount
, data
и setData
), чтобы виджеты знали, как оттуда брать и как обновлять данные.class ArticlesModel :
public QAbstractTableModel
{
public:
ArticlesModel(QObject *parent=nullptr);
void addArticle(const Article& art);
void removeArticle(int id);
//QAbstractTableModel interface implamentation
int rowCount(const QModelIndex &/*parent*/) const override;
int columnCount(const QModelIndex &/*parent*/) const override;
bool data(QModelIndex& index, const QVariant &value, int role) const override;
QVariant setData(QModelIndex& index, int role) override;
private:
std::vector<Article> _articles;
};
// =================================================================
ArticlesModel(QObject *parent/*=nullptr*/)
: QAbstractTableModel(parent)
{
}
void ArticlesModel::addArticle(const Article& art) {
_articles.push_back(art);
}
void ArticlesModel::removeArticle(int id) {
auto found = std::find_if(begin(_articles), end(_articles),
[id](const Article& art) {
art.id() == id;
});
if (found != std::end(_articles)) {
_articles.erase(artIt);
}
}
int ArticlesModel::rowCount(const QModelIndex &/*parent*/) const override {
return _articles.size();
}
int ArticlesModel::columnCount(const QModelIndex &/*parent*/) const override {
return 2;
}
bool ArticlesModel::data(QModelIndex& index, const QVariant &value, int role) const override {
if (!index.isValid) return QVariant();
if (role == Qt::EditRole) {
switch (column) {
case 0:
QVariant(_articles[index.row()].setTitle(value.toString()));
return true;
case 1:
QVariant(_articles[index.row()].setContent(value.toString()));
return true;
}
}
return false;
}
QVariant ArticlesModel::setData(QModelIndex& index, int role) override {
if (!index.isValid) return QVariant();
if (role == Qt::DisplayRole || role == Qt::EditRole) {
switch (column) {
case 0: return QVariant(_articles[index.row()].title());
case 1: return QVariant(_articles[index.row()].content());
}
}
return QVariant();
}
// this - это какой-то родительский виджет
auto titleEditor = new QLineEdit(this);
auto contentEditor = new QTextEdit(this);
QAbstractTableModel *model = new ArticlesModel(this);
model->addArticle(Article(1, "Hello title", "Hello content"));
model->addArticle(Article(2, "Another title", "Another content"));
auto mapper = new QDataWidgetMapper(this);
mapper->setModel(model);
mapper->addMapping(titleEditor, 0);
mapper->addMapping(contentEditor, 1);
mapper->toFirst(); // Переключаемся на первый элемент модели
model->add/removeArticle(const Article&)
, переходить с заметки на заметку с помощью mapper->setCurrentIndex(int index)
, менять содержимое заметок в редакторе.QListView
, так же передать туда модель через setModel()
и связать сигнал изменения текущего элемента списка с тем же действием mapper, добавить пару кнопок для добавления/удаления заметок и мы получим полноценный редактор.Didn't find what you were looking for?
Ask your questionAsk a Question
731 491 924 answers to any question