6

私のアプリケーションは、オブジェクトから継承するタイプのいくつかのオブジェクトを格納し QAbstractListModelます。

std::vector<T>これにより、単純なモデルまたはQList<T>一般的な追加、削除、および複数選択機能を備えたモデルにラップするときに、非常に多くの重複コードが生成さ れます。

その方法QAbstractListModelが使用されることになっているのですか、それとも重複したコードを削除できるアダプタークラスがありますか(少なくともQtの一部であるコンテナーの場合)?

例:モデルにラップvector<ObjectA>して入れたい。、などvector<ObjectB>のコードは常に同じであり、それを統合したいと思います(とでさえも機能する可能性のある少しのメタプログラミングを使用して)。insertRowsdeleteRowscolumnCounttupledata

4

2 に答える 2

6

Qtのc++への拡張(SIGNALS、SLOTSなど)はテンプレートではうまく機能しないため、これは2つの別々のクラスで行う必要があります。この理由と回避策は、https ://doc.qt.io/archives/qq/qq15-academic.htmlにあります。

これが解決策の大まかな概要です。(これは、アプリケーションで使用しているコードに基づいており、正常に機能しています。)

1.Qt関連の作業を行う抽象リストクラス

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.テンプレート処理を行う抽象クラス

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.実際のリストクラス

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. ...
};
于 2012-01-17T16:08:59.330 に答える
1

通常、私は直接から継承する独自のモデルを実装し、モデルに提供するデータストレージコンテナの処理QAbstractItemModelなどのプレゼンテーション関数に独自の実装を提供します。data()

使用するためのコードの重複がある場合はQList<T>std::vector<T>次のいずれかを実行して一方を他方に変換することをお勧めします。

QList<T> list = QList::fromVector(QVector::fromStdVector(vector));

または他の方法。

std::vector<T> vector = qlist.toVector().toStdVector();

私は後者を行いますが、どちらかを選択できます。

追加のコメントに基づいて、実行できるアクションの2つのパスがあります。

パス1:

次のように実装objectAobjectBます。

class objectA : baseObject

class objectB : baseObject

ここbaseObjectで:

struct baseObject
{
    virtual std::string toString() = 0;
};

おそらく他の何よりも文字列に変換する方が簡単です。

パス2は基本的にstd::vector<boost::any>()、データストレージコンテナとして使用するモデル内を含みます。このようにして、単一のモデルサブクラス化を実装できますQAbstractListModel

データストレージコンテナでデータの表示を共通化できる場合はdata()、要素を表示する関数が返される必要があり、要素QVariantを構築できるものが制限されるため、実行できる操作が制限されることを考慮する必要があります。から。

于 2012-01-17T14:46:23.230 に答える