属性编辑器设计模式?

时间:2009-08-20 04:06:18

标签: c++ design-patterns qt

2 个答案:

答案 0 :(得分:3)

冷静下来,你的代码没有O(n ^ 2)完整性。你有一个嵌套循环,但只有一个计入N(对象数),另一个计入固定数量的属性,这与N无关。所以你有O(N)。

对于静态变量,您编写“没有任何特定于实例的属性”,稍后您将撰写对象的各个属性的更新,这些属性是特定于实例的属性。也许你把“类属性”(当然在所有属性中共享)与个别属性混淆了?所以我认为你根本不需要静态成员。

是否要仅在对象出现时显示对象的更改,还是要进行连续显示?如果您的硬件能够处理后者,我建议采用这种方式。在这种情况下,您必须遍历所有对象并在此过程中更新它们。

编辑:区别在于前者(更新时更新),绘图由更改值的操作启动,例如对象移动。对于后者,一个连续显示,你会添加一个QTimer,每秒激发60次并调用一个SLOT(render())来实现所有对象的实际渲染。根据变化的速度,这实际上可能更快。它可能更容易实现。 另一个可能性是让Qt使用图形视图来处理整个绘图,它在一个非常有效的树结构中内部处理要绘制的对象。看一眼 http://doc.trolltech.com/4.5/graphicsview.html

如果只想显示更改,可以为每个属性值使用单独的回调。每次更改属性的值(在这种情况下使属性值为private并使用setSomeThing(value))时,都使用emit(update())调用update函数。如果你绝对关注发射慢,你可以通过函数指针使用“真正的”回调,但我不建议,Qt的连接/信号/插槽更容易使用。在大多数情况下,开销确实可以忽略不计。

答案 1 :(得分:3)

您是否看过Qt的(dynamic) property system

bool QObject::setProperty ( const char * name, const QVariant & value );
QVariant QObject::property ( const char * name ) const
QList<QByteArray> QObject::dynamicPropertyNames () const;
//Changing the value of a dynamic property causes a 
//QDynamicPropertyChangeEvent to be sent to the object.


function valueChanged(property, value) {
       foreach(selectedObj as obj) {
           obj->setProperty(property, value);
   }
} 

实施例

这是一个不完整的例子,可以让您了解我对物业系统的看法。
我想SelectableItem * selectedItem必须替换为您案例中的项目列表。

class SelectableItem : public QObject
{
    Q_OBJECT
    Q_PROPERTY(QString name READ name WRITE setName );
    Q_PROPERTY(int velocity READ velocity WRITE setVelocity);

public:
    QString name() const { return m_name; }
    int velocity() const {return m_velocity; }

public slots:
    void setName(const QString& name) 
    {
        if(name!=m_name)
        {
            m_name = name;
            emit update();
        }
    }
    void setVelocity(int value)
    {
        if(value!=m_velocity)
        {
            m_velocity = value;
            emit update();
        }
    }

signals:
    void update();

private:
    QString m_name;
    int m_velocity;
};

class MyPropertyWatcher : public QObject
{
    Q_OBJECT
public:
    MyPropertyWatcher(QObject *parent) 
    : QObject(parent), 
      m_variantManager(new QtVariantPropertyManager(this)),
      m_propertyMap(),
      m_selectedItem(),
      !m_updatingValues(false)
    {
        connect(m_variantManager, SIGNAL(valueChanged(QtProperty*, QVariant)), SLOT(valueChanged(QtProperty*,QVariant)));
        m_propertyMap[m_variantManager->addProperty(QVariant::String, tr("Name"))] = "name";
        m_propertyMap[m_variantManager->addProperty(QVariant::Int, tr("Velocity"))] = "velocity";
        // Add mim, max ... to the property
        // you could also add all the existing properties of a SelectableItem
        // SelectableItem item;
        // for(int i=0 ; i!=item.metaObject()->propertyCount(); ++i)
        // {
        //     QMetaProperty metaProperty(item.metaObject()->property(i));
        //     QtProperty *const property 
        //         = m_variantManager->addProperty(metaProperty.type(), metaProperty.name());
        //     m_propertyMap[property] = metaProperty.name()
        // }
    }

    void setSelectedItem(SelectableItem * selectedItem)
    {
        if(m_selectedItem)
        {
            m_selectedItem->disconnect( this );
        }

        if(selectedItem)
        {
            connect(selectedItem, SIGNAL(update()), SLOT(itemUpdated()));
            itemUpdated();
        }
        m_selectedItem = selectedItem;
    }


private slots:
    void valueChanged(QtProperty *property, const QVariant &value)
    {
        if(m_updatingValues)
        {
            return; 
        }

        if(m_selectedItem && m_map)
        {
            QMap<QtProperty*, QByteArray>::const_iterator i = m_propertyMap.find(property);
            if(i!=m_propertyMap.end())
                m_selectedItem->setProperty(m_propertyMap[property], value);
        }
    }  

    void itemUpdated()
    {
        m_updatingValues = true;
        QMapIterator<QtProperty*, QByteArray> i(m_propertyMap);
        while(i.hasNext()) 
        {
            m_variantManager->next();
            m_variantManager->setValue(
                i.key(), 
                m_selectedItem->property(i.value()));                
        }
        m_updatingValues = false;
    }

private:
    QtVariantPropertyManager *const m_variantManager;
    QMap<QtProperty*, QByteArray> m_propertyMap;
    QPointer<SelectableItem> m_selectedItem;
    bool m_updatingValues;
};