【问题标题】:generalization of mapping a multi-variable/layer system映射多变量/层系统的概括
【发布时间】:2012-06-25 18:23:56
【问题描述】:

我用 C++ / QT 编写了一个应用程序,它与设备通信以读取/写入其变量,将它们放入/获取到结构中并在 gui 中呈现它们用于查看/编辑目的。

1) 该设备附带一个示例 c 代码,该代码还定义了通信协议(以非常糟糕的方式),例如:

#define VALUE_1 0x12345678
#define VALUE_2 0xDEADBEEF
#define MY_DEVICE_VAR (VALUE_1 << 4) & (VALUE_2 >> 6)
#define MY_DEVICE_VAR_1 (MY_DEVICE_VAR & (VALUE_1 << 2)
#define MY_DEVICE_VAR_2 (MY_DEVICE_VAR & (VALUE_2 << 4)
#define MY_DEVICE_VAR_2 (MY_DEVICE_VAR & (VALUE_2 << 4)
// .. and 300 more lines like above

所以变量VAR_1 表示为:MY_DEVICE_VAR_1

2) 我有一个包含设备所有变量的结构:

struct MyDeviceData
{
    int var1;
    double var2;
    char var3;
    bool var4;
        .
        .
};

它基本上是从设备读取的数据的存储/投影。 POD 变量有 4 种不同类型。

3) 最后我的 gui 有 gui 元素来显示和编辑 MyDeviceData 的实例

class MyGuI
{
    QLineEdit var1;
    QLineEdit var2;
    QComboBox var3;
    QCheckBox var4;
       .
       .
};

现在我的问题是:

1) 我正在映射 MY_DEVICE_VAR1 -> MyDeviceData::var1 -> MyGUI::var1ifswitch/case 声明,我对此并不感到自豪。进行映射的更好的“程序化”方式是什么?

2) 当 gui 元素的值发生变化时,我想将更新后的值发送到卡片。除了覆盖“textChangedselectedIndexChanged”等事件的处理函数之外,还有什么“更智能”的方法吗? (QSignalMapper?)

3) 在这种项目中,是否可以概括整个苦力工作? (代码生成器工具?模板?)

【问题讨论】:

    标签: c++ qt user-interface serialization


    【解决方案1】:

    我最近遇到了完全相同的问题,尽管我是设计设备、固件和通信协议的人。

    我认为必须使用模型/视图来保持理智。

    我将所有变量作为派生自QAbstractTableModel 的数据模型类中的元素。那是因为有固定数量的简单参数(行),并且每个设备(列)都相同。不过,很快,我将不得不转向树模型,因为某些参数内部结构为列表、向量或矩阵,将它们直接暴露给视图会很有帮助,而不仅仅是格式化字符串.

    模型类也有一些方便的getter/setter,这样你就不必通过它们的行/列来引用参数。通过QModelIndex 访问的行/列仅供视图使用。

    我选择使用 UserRole 来直接表示值(大多数是 SI 单位的两倍),并选择使用 Display 和 Edit 角色来将格式化/缩放的数据呈现给小部件。

    对于非视图控件,需要一个活页夹对象。 QDataWidgetMapper 由 Qt 提供,您最好使用它。

    前段时间我没有注意到有小部件映射器,所以我编写了一个自定义绑定器对象(从 QObject 派生),它为每个 GUI 控件实例化,以将模型的某个索引绑定到非-查看 Qt 控件小部件。另一种方法是使用QListViews,每个视图都有一个代理模型,只公开一个元素,并正确分配委托。不过,这会带来很多开销。 binder 对象方法非常轻量级。

    模型视图方法还使人们能够轻松地找出每个控件的最新指示。

    • 当应用程序首次启动时,模型可以指示(通过专用角色)这些值是无效的。这可以在控件上放置一个 x-cross 或理发杆,以清楚地指示那里没有有效值。

    • 当设备处于活动状态并且用户修改控件时,不同的角色可以指示模型中的值已更改,但尚未传播到设备。

    • 当设备通信代码从模型中获取更改并将其提交给设备时,它可以告诉模型,视图(实际上是 biner)会自动获取并更新控制。

    • 向模型添加Model * clone() const 方法,或添加序列化/反序列化操作符,可以让您轻松拍摄模型快照,并实现撤消/重做、提交/恢复等。

    binder的相关sn-ps在这里:

    // constructor
    Binder::Binder(QAbstractItemModel * model_, const QModelIndex & index_, QObject * object) :
       QObject(object),
       model(model_),
       index(index_),
       sourceRole(Qt::DisplayRole),
       property(""),
       target(object),
       lockout(false)
    {
       Q_ASSERT(index.isValid());
       // replicate for each type of control
       if (qobject_cast<QDoubleSpinBox*>(object)) {
          connect(object, SIGNAL(valueChanged(double)), SLOT(doubleSpinBoxGet(double)));
          connect(index.model(), SIGNAL(dataChanged(QModelIndex, QModelIndex)), SLOT(doubleSpinBoxSet(QModelIndex, QModelIndex)));
       }
       else if (....) 
    }
    
    // getter/setter for QDoubleSpinBox
    
    void Binder::doubleSpinBoxGet(double val)
    {
       if (lockout) return;
       QScopedValueRollback<bool> r(lockout);
       lockout = true;
       model->setData(index, val, sourceRole);
    }
    
    void Binder::doubleSpinBoxSet(const QModelIndex & tl, const QModelIndex & br)
    {
       if (lockout) return;
       if (! isTarget(tl, br)) return;
       QScopedValueRollback<bool> r(lockout);
       lockout = true;
       if (! index.data().canConvert<double>()) return;
       qobject_cast<QDoubleSpinBox*>(target)->setValue(index.data(sourceRole).toDouble());
    }
    
    // helper
    
    bool Binder::isTarget(const QModelIndex & topLeft, const QModelIndex & bottomRight)
    {
       return topLeft.parent() == bottomRight.parent()
              && topLeft.parent() == index.parent()
              && topLeft.row() <= index.row()
              && topLeft.column() <= index.column()
              && bottomRight.row() >= index.row()
              && bottomRight.column() >= index.column();
    }
    

    【讨论】:

      猜你喜欢
      • 2011-03-26
      • 2011-01-02
      • 2020-09-09
      • 1970-01-01
      • 2012-07-06
      • 2022-01-25
      • 1970-01-01
      • 1970-01-01
      • 2014-08-17
      相关资源
      最近更新 更多