3

我有一个分层数据结构,可以在几个 Qt 视图(或小部件)中可视化。数据层次结构由异构元素类型组成,例如:

House
 |- Floor
 |   |- Room
 |   |   |- Window
 |   |   |- ...
 |   |- Room
 |   |   |- ...
 |- ...

所有元素(House、Floor、Room、...)都有可以显示的属性。请注意,这是一个简化的示例。层次结构由各种视图绘制。例如,模板列表中的房间标识符(QListView/Widget)、自定义视图(每个元素的 QWidget 子类的层次结构)、编辑楼层属性的详细视图(QWidget 子类或 QWizard)。

也可以在多个实例之间拖放元素。例如将房间搬到不同的楼层。可以将特定楼层声明为模板并从模板列表中拖动楼层,例如自定义视图(组成房屋的位置)。

Qt 使用模型/视图架构来分离数据、模型和视图。因为我有完全不同类型的视图,我假设每个视图都需要一个对应的模型。在我的自定义层次结构视图中,每个元素都有自己的可视化,因此层次结构存在(但不应该存在)三个:数据层次结构、模型层次结构和视图层次结构。这变得非常混乱,因为如果一个元素被拖放、删除或复制,每个层次结构都必须更新。更好的方法是Presentation-Abstraction-Control图案。但是,PAC 不适用,因为必须设置 QWidget 的父级,才能将子级嵌入到父级视图中。因此,QWidget 不能引用负责对层次结构建模的代理。

在我看来,Qt 在表示同类数据类型(如字符串)的列表、表格和树方面非常出色。在我的例子中,每个元素都有一组单独的属性,不能简单地以表格的形式表示。在这个讨论中,不鼓励将方形钉子强行插入圆孔中。意思是,不要在表格表示中强制任何设计。

我的问题的核心是将以下功能统一在一个设计概念中: 具有不同细节级别的分层数据的可视化。支持视图之间的拖放,复制数据并生成适当的模型/视图组件。支持视图中的拖放,这会影响数据、模型和视图层次结构(我想避免实现三次)。我不能为一个包含所有子组件的房子提供一个模型,因为地板和房间太复杂了。我发现为一个拖放、删除或复制操作管理三个(或更多)层次结构很笨拙。

是否有最佳实践、设计模式或解决我的问题的不同方法?Qt可以解决这个问题吗?

我感谢每一个建议。

4

1 回答 1

0

I had a similar issue for a while with my hierarchical structure. Everything in Qt's model-view-delegate architecture hinges on how you organize your data and how complex you're willing to get. For very simple applications, it makes sense to implement things from an item-based approach, editing item display at the View level. This gets very messy very fast.

Sounds like you're willing to get pretty complex, so I'd recommend taking a model-based approach. You can control nearly everything at the model level, including some basic display elements, data organization, and (most importantly) heirarchies.

I found it helpful when getting started to have my objects inherit QStandardItem and subclassing QStandardItemModel, since QStandardItem already had the parent-child hierarchy and indexing set up for me. I like incrementing Qt::UserRole and assigning an enum value to each of my custom data types. For example:

enum FloorProperties
{
    DAT_CARPETING = Qt::UserRole +100,
    DAT_AREA = Qt::UserRole +101,
    DAT_FLOORNUM = Qt::UserRole +102
}

Even if you don't want to associate a stored value with every data role (using the convenient QStandardItem::setData()), you can customize QStandardItemModel::data() to return a computed value, stored value, whatever. Customizing the model allows you to think about each item as an object, rather than a single cell in the table/list.

The standard views should give you most of what you need on a general basis. Customize display for certain data types (Floors, Windows, integers, strings, etc) using delegates. Hope that makes some sense.

于 2013-04-16T16:28:55.380 回答