从表单的小部件中收集值

Posted

技术标签:

【中文标题】从表单的小部件中收集值【英文标题】:Collecting values from form's widgets 【发布时间】:2015-12-17 14:25:38 【问题描述】:

鉴于以下情况:

struct Property 
  QWidget *label;
  QWidget *field;
;
QList<Property*> properties;

其中大部分fields 是QLineEdits,但有些是QTimeEdits 并且可能是其他类型,例如QDateEdit

这用于(方便地)以这种方式制作表单:

for(int i = 0; i != properties.size(); i++)
    formLayout->addRow( properties.at(i)->label,properties.at(i)->field );

我正在考虑以同样的方式从表单的fields 中收集值:

foreach (const Property *p, properties) 
    p->field->value()

问题是没有value()这个函数。

这个设计好吗?为了实现value(),应该采用哪种方法?

【问题讨论】:

【参考方案1】:

有多种方法可以做到这一点。

    一种丑陋的方法是使用p-&gt;metaObject()-&gt;className() 方法。 更好的方法是将qobject_cast&lt;Class*&gt;(p) 用于所有可能的类型。不为 NULL 的那个是正确的类型。 您可以使用p-&gt;inherits("CLASS") 请求继承。

【讨论】:

【参考方案2】:

天真的方法是预先对所有可能性进行硬编码,方法是:

if (QLineEdit *le = qobject_cast<QLineEdit *>(obj)) 
    le->text(); 
 else if (QDateTimeEdit *dte = qobject_cast<QDateTimeEdit *>(obj)) 
    dte->dateTime();
 else if (...)  // repeat for all the cases



适当的稳健的方法是利用 Qt 的元对象功能。特别是a class can mark one of its properties to be the USER property,即用户与之交互的属性。这是为 Qt 自己的编辑小部件完成的。

所以好的和通用的方法是:

QVariant result;
QMetaObject *mo = obj->metaObject();
const int propertyCount = mo->propertyCount();
for (int i = 0; i < propertyCount; ++i) 
    QMetaProperty mp = mo->property(i);
    if (mp.isUser(obj))  
        result = mp.read(obj);
        break;
    

// use result

【讨论】:

以上是关于从表单的小部件中收集值的主要内容,如果未能解决你的问题,请参考以下文章

如何关闭在提升的小部件中单击的按钮上的 qt 小部件 ui?

如何从另一个窗口访问一个窗口的小部件?

用新的小部件替换 QTabWidget 的页面

Django Modeltranslation:TranslationAdmin 类未复制正确的小部件

颤振步进器小部件 - 在各个步骤中验证字段

Flutter/Dart:我的小部件树中可以有多个带有状态的小部件吗?