Название: [РЕШЕНО] Обновление данных view при обновлении модели
Отправлено: tyorn от Август 21, 2015, 11:31
Собственно модель - наследник QAbstractListModel, представление - GridView. Проблема в том, что по doubleClick на элементе я должен изменить текст внутри него. относительно документации реализовал в наследнике setData и flags, при доблклике в модели проиходит обновление значения по роли, но обратно представление его уже не получает. хотя явный вызов dataChanged присутствует, т.е. не срабатвает привязка что-ли. ниже код @audioTrackSetupModel.h #ifndef AUDIOTRACKSETUPMODEL_H #define AUDIOTRACKSETUPMODEL_H
#include <QObject> #include <QAbstractListModel> #include <QList> #include <QVariant> #include <QMetaType>
class AudioTrackItem : public QObject { Q_OBJECT Q_PROPERTY(QString text READ text WRITE setText NOTIFY textChanged) Q_PROPERTY(bool selected READ selected WRITE setSelected NOTIFY selectedChanged) Q_PROPERTY(bool enabled READ enabled WRITE setEnabled NOTIFY enabledChanged) public: AudioTrackItem(QString text = "", bool selected = false, bool enabled = false, QObject *parent = 0);
QString text() const; void setText(QString text);
bool selected() const; void setSelected(bool value);
bool enabled() const; void setEnabled(bool state);
signals: void textChanged(); void selectedChanged(); void enabledChanged();
private: QString m_text; bool m_selected; bool m_enabled; };
class AudioTrackSetupModel : public QAbstractListModel { Q_OBJECT public: enum ATSRItemRoles { TextRole = Qt::UserRole + 1, SelectedRole, LabelsRole }; AudioTrackSetupModel(QObject *parent = 0);
int rowCount(const QModelIndex &parent = QModelIndex()) const; QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const;
bool setData(const QModelIndex &index, const QVariant &value, int role = Qt::DisplayRole); Qt::ItemFlags flags(const QModelIndex &index) const;
void initGrid();
public slots: QList<QVariant> chLabels() const; bool isInSelection(QVariant index) const;
private: QList<AudioTrackItem* > m_items; QHash<int, QByteArray> roleNames() const; int m_selectedRow; };
#endif // AUDIOTRACKSETUPMODEL_H
@audioTrackSetupModel.cpp #include "audiotracksetupmodel.h" #include <QDebug>
AudioTrackItem::AudioTrackItem(QString text, bool selected, bool enabled, QObject *parent) : QObject(parent), m_text(text), m_selected(selected), m_enabled(enabled) {
}
QString AudioTrackItem::text() const { return m_text; }
void AudioTrackItem::setText(QString text) { if (m_text != text) { m_text = text; emit textChanged(); } }
bool AudioTrackItem::selected() const { return m_selected; }
void AudioTrackItem::setSelected(bool value) { if (m_selected != value) { m_selected = value; emit selectedChanged(); } }
bool AudioTrackItem::enabled() const { return m_enabled; }
void AudioTrackItem::setEnabled(bool state) { if (m_enabled != state) { m_enabled = state; emit enabledChanged(); } }
AudioTrackSetupModel::AudioTrackSetupModel(QObject *parent) : QAbstractListModel(parent), m_selectedRow(-1) {
}
int AudioTrackSetupModel::rowCount(const QModelIndex &parent) const { Q_UNUSED(parent); return m_items.count(); // return 1024; // 32 ch * 32 ch }
QHash<int, QByteArray> AudioTrackSetupModel::roleNames() const { QHash<int, QByteArray> roles; roles[TextRole] = "text"; roles[SelectedRole] = "selected"; roles[LabelsRole] = "labels"; return roles; }
QVariant AudioTrackSetupModel::data(const QModelIndex &index, int role) const {
if (role == TextRole) { return m_items[index.row()] -> text(); } if (role == SelectedRole) { return m_items[index.row()] -> selected(); } if (role == LabelsRole) { return chLabels(); } return QVariant(); }
void AudioTrackSetupModel::initGrid() { for (int i = 0; i < 1024; ++i) { beginInsertRows(QModelIndex(), rowCount(), rowCount()); m_items.append(new AudioTrackItem); endInsertRows(); } }
Qt::ItemFlags AudioTrackSetupModel::flags(const QModelIndex &index) const { return (QAbstractListModel::flags(index)|Qt::ItemIsEditable); }
bool AudioTrackSetupModel::setData(const QModelIndex &index, const QVariant &value, int role) { if (role == TextRole) { qDebug()<<index.row(); m_items[index.row()] -> setText(value.toString()); qDebug()<<m_items[index.row()]->text(); //emit dataChanged(QAbstractListModel::createIndex(index.row(), 0), QAbstractListModel::createIndex(index.row(), 0)); emit dataChanged(QAbstractListModel::createIndex(0, 0), QAbstractListModel::createIndex(1024, 0)); return true; } if (role == SelectedRole) { if (m_selectedRow != index.row() / 32) { if (m_selectedRow >= 0) { for (int i = m_selectedRow * 32; i < (m_selectedRow + 1) * 32; ++i) m_items[i] -> setSelected(false); emit dataChanged(QAbstractListModel::createIndex(m_selectedRow * 32, 0), QAbstractListModel::createIndex((m_selectedRow + 1) * 32, 0)); } m_selectedRow = index.row() / 32; for (int i = m_selectedRow * 32; i < (m_selectedRow + 1) * 32; ++i) m_items[i] -> setSelected(value.toBool()); emit dataChanged(QAbstractListModel::createIndex(m_selectedRow * 32, 0), QAbstractListModel::createIndex((m_selectedRow + 1) * 32, 0)); //emit dataChanged(QAbstractListModel::createIndex(0, 0), QAbstractListModel::createIndex(1024, 0)); return true; } } return false; }
QList<QVariant> AudioTrackSetupModel::chLabels() const { QList<QVariant> tl; for (int i = 0; i < 32; ++i) { tl<<QVariant::fromValue(i + 1); } return tl; }
bool AudioTrackSetupModel::isInSelection(QVariant index) const { return index.toInt() == m_selectedRow; }
@main.qml import QtQuick 2.0 import "Style.js" as S
Rectangle { width: 800 height: 800
property int gridItemWidth: 20 property int gridItemHeight: 15 property int marginSize: 1 color: S.blueBackgroundColor
GridView { id: grid width: 32 * gridItemWidth height: 32 * gridItemHeight model: atm cellWidth: gridItemWidth cellHeight: gridItemHeight
header: chLabels footer: chLabels
Component { id: chLabels Rectangle { width: grid.width - 2 * marginSize height: gridItemHeight - 2 * marginSize color: "transparent"
ListView { width: parent.width height: parent.height model: atm.chLabels() //labels orientation: ListView.Horizontal delegate: Rectangle { width: gridItemWidth height: gridItemHeight color: "transparent" Text { text: modelData// + 1 color: modelData === 5 ? S.yellowColor : S.orangeColor anchors.centerIn: parent } } } } }
delegate: Rectangle { width: gridItemWidth - 2 * marginSize height: gridItemHeight - 2 * marginSize color: S.blueBackgroundColor
border { width: 1 color: selected ? S.yellowColor :S.blueColor }
Rectangle { width: parent.width - 2 * parent.border.width height: parent.height - 2 * parent.border.width anchors.centerIn: parent
color: selected ? S.yellowColor : S.blueBackgroundColor opacity: text === "" && selected ? 0.25 : 1
Text { id: textBox1 text: text color: S.blackColor font.pixelSize: S.mediumTextSize - 1 anchors.centerIn: parent //z: 1 } }
MouseArea { anchors.fill: parent
onClicked: { selected = !selected console.log("qml:", text) console.log("textBox1", textBox1.text) }
onDoubleClicked: { text = "5" //textBox1.text = "5" } } } }
}
@main.cpp #include <QGuiApplication> #include <QQuickView> #include <QQmlContext> #include <QDebug>
#include "audiotracksetupmodel.h"
int main(int argc, char *argv[]) { QGuiApplication app(argc, argv); QQuickView view;
AudioTrackSetupModel atm; atm.initGrid();
view.rootContext()->setContextProperty("atm", &atm);
view.setSource(QUrl(QStringLiteral("qrc:/main.qml"))); view.show();
return app.exec(); }
Вывод вот этих значений console.log("qml:", text) console.log("textBox1", textBox1.text) показывает как раз, что в модели значение изменилось, qml его успешно читает при этом как новое, в то же время не изменилось значение текста для textBox1, хотя его значение это же вроде как привязка по роли: Text { id: textBox1 text: text ...
Название: Re: Обновление данных view при обновлении модели
Отправлено: tyorn от Август 21, 2015, 11:44
Upd: назвать роль именем свойства компонента было плохой идеей. собственно только в этом и проблема. к сожалению, тему удалить / закрыть не могу
Название: Re: [РЕШЕНО] Обновление данных view при обновлении модели
Отправлено: Пантер от Август 21, 2015, 12:35
Удалять не нужно, отметил как решенную. Вдруг, кто еще напорется.
|