QAbstractListModel和QList适配器

时间:2012-01-17 13:30:20

标签: qt qabstractitemmodel qabstractlistmodel

我的应用程序存储了一些继承自的类型的对象 QAbstractListModel个对象。

这在包装简单时会生成大量重复的代码 使用常规添加的std::vector<T>QList<T>模型, 删除和多选功能。

这是QAbstractListModel应该使用的方式还是存在的方式 一些可以删除重复代码的适配器类(至少对于 容器是Qt的一部分?

示例:我想将vector<ObjectA>vector<ObjectB>包装到模型中。 insertRowsdeleteRowscolumnCount等的代码总是一样的,我想整合一下(通过一些甚至可以用于{的小元编程) {1}}和tuple)。

2 个答案:

答案 0 :(得分:6)

你必须在两个单独的类中执行此操作,因为Qt对c ++的扩展(SIGNALS,SLOTS等)不能很好地与模板一起使用。有关此问题的基本原理和解决方法,请访问:http://doc.qt.digia.com/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. ...
};

答案 1 :(得分:1)

通常我会直接从QAbstractItemModel继承我自己的模型,并为data()这样的表示函数提供我自己的实现来处理我给模型的数据存储容器。

如果您使用QList<T>std::vector<T>进行代码重复,那么我建议您将其中一个转换为另一个:

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

或其他方式。

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

我会做后者,但你可以选择。

根据您的其他评论,您可以采取以下两种行动方式:

路径1:

实施objectAobjectB,如下所示:

class objectA : baseObject

class objectB : baseObject

其中baseObject是:

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

可能更容易转换为字符串,然后其他任何东西。

路径2基本上涉及使用std::vector<boost::any>()作为数据存储容器的模型内部,这样就可以实现单个模型子类化QAbstractListModel

你需要考虑的事情是,如果您的数据存储容器可能使数据显示变得普遍,那么您可以做的事情是有限的,因为data()函数将为您的视图提供元素必须返回{ {1}}它限制了你可以从中构建它。