QAbstractListModel und QList Adapter
-
29-10-2019 - |
Frage
Meine Anwendung speichert einige Objekte eines Typs, der von erbt
QAbstractListModel
Gegenst.
Dies erzeugt beim Umschließen eines einfachen Codes ziemlich viel doppelten Code
std::vector<T>
oder ein QList<T>
in das Modell mit dem allgemeinen add,
lösch- und Mehrfachauswahl-Funktionalität.
Ist das der Weg QAbstractListModel
soll benutzt werden oder ist da
einige Adapterklassen, die den doppelten Code entfernen können (zumindest für
container, die Teil von Qt sind)?
Beispiel:Ich möchte wickeln vector<ObjectA>
und vector<ObjectB>
in ein Modell.Der Code für insertRows
, deleteRows
, columnCount
usw.wird immer gleich sein und ich möchte das konsolidieren (mit ein wenig Metaprogrammierung, die sogar mit funktionieren könnte tuple
und data
).
Lösung
Sie müssen dies in zwei separaten Klassen tun, da die Erweiterungen von Qt zu c ++ (SIGNALE, SLOTS usw.).) spielen Sie nicht gut mit Vorlagen.Die Begründung und Problemumgehung dafür finden Sie unter: http://doc.qt.digia.com/qq/qq15-academic.html
Hier ist eine grobe Skizze einer Lösung.(Dies basiert auf Code, den wir in unserer Anwendung verwenden und der einwandfrei funktioniert.)
1.Abstrakte Listenklasse, die Qt-Sachen macht
class FooListModelQt : public QAbstractTableModel {
Q_OBJECT
public:
// Non-template methods, signals, slots, etc. can be used here. For example...
QSet<int> SelectedRows() const;
// ... etc. ...
signals:
void SelectionChanged();
// ... etc. ...
protected:
explicit FooListModelQt(QObject *parent = NULL);
virtual ~FooListModelQt() = 0;
// ... etc. ...
};
2.Abstrakte Klasse, die Template-Sachen macht
template <typename T>
class FooListModel : public FooListModelQt {
public:
const T* at(int index) const { return items_.at(index); }
int count() const { return items_.count(); }
void Append(T *item);
// ... etc. ...
protected:
explicit FooListModel(QObject *parent = NULL);
virtual ~FooListModel();
private:
QList<T*> items_;
};
3.Aktuelle Listenklasse
class BarListModel : public FooListModel<Bar> {
Q_OBJECT
public:
explicit BarListModel(QObject *parent = NULL);
int columnCount(const QModelIndex &parent) const;
QVariant data(const QModelIndex &index, int role) const;
// ... etc. ...
};
Andere Tipps
Normalerweise würde ich mein eigenes Modell implementieren, das von erbt QAbstractItemModel
direkt und stelle meine eigene Implementierung für die Präsentationsfunktionen wie z data()
um mit dem Datenspeichercontainer umzugehen, gebe ich das Modell.
Wenn Sie Code-Duplizierung zur Verwendung haben QList<T>
und std::vector<T>
dann würde ich vorschlagen, das eine in das andere umzuwandeln, indem ich entweder folgendes tue:
QList<T> list = QList::fromVector(QVector::fromStdVector(vector));
oder andersherum.
std::vector<T> vector = qlist.toVector().toStdVector();
Ich würde Letzteres tun, aber Sie können auch wählen.
Basierend auf Ihren zusätzlichen Kommentaren gibt es 2 Handlungsmöglichkeiten, die Sie ergreifen können:
Weg 1:
Implementieren objectA
und objectB
wie folgt:
class objectA : baseObject
und
class objectB : baseObject
wo baseObject
is:
struct baseObject
{
virtual std::string toString() = 0;
};
Wahrscheinlich einfacher in String zu konvertieren als alles andere.
Pfad 2 beinhaltet im Wesentlichen die Verwendung innerhalb des Modells std::vector<boost::any>()
auf diese Weise können Sie als Datenspeichercontainer eine einzelne Modellunterklasse implementieren QAbstractListModel
.
Die Sache, die Sie berücksichtigen müssen, dass, wenn Ihr Datenspeichercontainer Sie wahrscheinlich die Datenpräsentation gemeinsam machen können, Sie begrenzt sind, was Sie tun können, weil data()
funktion, die Ihrer Ansicht gibt, dass das Element zurückgegeben werden muss QVariant
und es ist begrenzt auf das, woraus Sie es konstruieren können.