2009-08-25 120 views
0

this question稍有关系,但你并不需要阅读它。该截图是有帮助的,但:奇怪的Qt错误(关于属性编辑器)

那么是什么发生的是,当你点击一个对象,更改属性,取消选择,然后重新选择它,属性编辑器将被重置为全0,即使那些AREN实际值。当您实际点击编辑器中的文本框时,会显示正确的值。这是否意味着它只是一个显示问题或什么?编辑如何有两个不同的价值观? 只有当突出显示的行(带有箭头)保持不变时才会发生这种情况 - 如果它们被注释掉,则不会发生。代码:

void PropertyBrowser::objectUpdated() { 
    if(m_selectedObjects.isEmpty()) { 
     return; 
    } 
    m_variantManager->disconnect(this); // <--- THIS LINE 
    QMapIterator<QtProperty*, QByteArray> i(m_propertyMap); 
    bool diff; 
    while(i.hasNext()) { 
     i.next(); 
     diff = false; 
     for(int j = 1; j < m_selectedObjects.size(); ++j) { 
      if(m_selectedObjects.at(j)->property(i.value()) != m_selectedObjects.at(j - 1)->property(i.value())) { 
       diff = true; 
       break; 
      } 
     } 
     if(diff) setBackgroundColor(topLevelItem(i.key()), QColor(232,232,232)); 
     else setBackgroundColor(topLevelItem(i.key()), Qt::white); 
     m_variantManager->setValue(i.key(), m_selectedObjects.first()->property(i.value())); 
    } 

    connect(m_variantManager, SIGNAL(valueChanged(QtProperty*, QVariant)), 
      this, SLOT(valueChanged(QtProperty*, QVariant))); // <--- AND THIS LINE 
} 

不过,我需要那些行,因为他们阻止setValue从触发valueChanged信号引起的其他问题。这似乎表明,调用该函数修复该问题:

void PropertyBrowser::valueChanged(QtProperty *property, const QVariant &value) { 
    if(m_propertyMap.find(property) != m_propertyMap.end()) { 
     foreach(QObject *obj, m_selectedObjects) { 
      obj->setProperty(m_propertyMap[property], value); 
     } 
    } 
} 

但是,该函数的作用的唯一的事情就是更新实际的对象...它无关,与属性编辑器(或不应该) 。如果你需要的话,这里是整个班级:

/* 
* File: PropertyBrowser.cpp 
* Author: mark 
* 
* Created on August 23, 2009, 10:29 PM 
*/ 

#include <QtCore/QMetaProperty> 
#include "PropertyBrowser.h" 

PropertyBrowser::PropertyBrowser(QWidget* parent) 
: QtTreePropertyBrowser(parent), m_variantManager(new QtVariantPropertyManager(this)) { 
    setHeaderVisible(false); 
    setPropertiesWithoutValueMarked(true); 
    setIndentation(10); 
    setResizeMode(ResizeToContents); 
    setFactoryForManager(m_variantManager, new QtVariantEditorFactory); 
    setAlternatingRowColors(false); 
    connect(m_variantManager, SIGNAL(valueChanged(QtProperty*, QVariant)), 
      this, SLOT(valueChanged(QtProperty*, QVariant))); 
} 

void PropertyBrowser::valueChanged(QtProperty *property, const QVariant &value) { 
    if(m_propertyMap.find(property) != m_propertyMap.end()) { 
     foreach(QObject *obj, m_selectedObjects) { 
      obj->setProperty(m_propertyMap[property], value); 
     } 
    } 
} 

QString PropertyBrowser::humanize(QString str) const { 
    return str.at(0).toUpper() + str.mid(1).replace(QRegExp("([a-z])([A-Z])"), "\\1 \\2"); 
} 

void PropertyBrowser::setSelectedObjects(QList<QObject*> objs) { 
    foreach(QObject *obj, m_selectedObjects) { 
     obj->disconnect(this); 
    } 
    clear(); 
    m_variantManager->clear(); 
    m_selectedObjects = objs; 
    m_propertyMap.clear(); 
    if(objs.isEmpty()) { 
     return; 
    } 
    for(int i = 0; i < objs.first()->metaObject()->propertyCount(); ++i) { 
     QMetaProperty metaProperty(objs.first()->metaObject()->property(i)); 
     QtProperty * const property 
       = m_variantManager->addProperty(metaProperty.type(), humanize(metaProperty.name())); 
     property->setEnabled(metaProperty.isWritable()); 
     m_propertyMap[property] = metaProperty.name(); 
     addProperty(property); 
    } 
    foreach(QObject *obj, m_selectedObjects) { 
     connect(obj, SIGNAL(propertyChanged()), SLOT(objectUpdated())); 
    } 
    objectUpdated(); 
} 

void PropertyBrowser::objectUpdated() { 
    if(m_selectedObjects.isEmpty()) { 
     return; 
    } 
    m_variantManager->disconnect(this); // <--- 
    QMapIterator<QtProperty*, QByteArray> i(m_propertyMap); 
    bool diff; 
    while(i.hasNext()) { 
     i.next(); 
     diff = false; 
     for(int j = 1; j < m_selectedObjects.size(); ++j) { 
      if(m_selectedObjects.at(j)->property(i.value()) != m_selectedObjects.at(j - 1)->property(i.value())) { 
       diff = true; 
       break; 
      } 
     } 
     if(diff) setBackgroundColor(topLevelItem(i.key()), QColor(232,232,232)); 
     else setBackgroundColor(topLevelItem(i.key()), Qt::white); 
     m_variantManager->setValue(i.key(), m_selectedObjects.first()->property(i.value())); 
    } 

    connect(m_variantManager, SIGNAL(valueChanged(QtProperty*, QVariant)), // <--- 
      this, SLOT(valueChanged(QtProperty*, QVariant))); 
} 

如果你想使用它,它是非常酷的类。让我们编辑任何QObject的属性,因为它们附有Q_PROPERTYs。

相关类:http://qt.nokia.com/products/appdev/add-on-products/catalog/4/Widgets/qtpropertybrowser/

回答

2

你什么都连接到m_variantManager?断开线路将断开与“this”的所有连接,但只连接一个插槽。

不确定这是否会解决某些问题,但可以使用object-> blockSignals(true)在一个对象上停止信号。这将关闭对象,直到您使用false调用该函数。

尝试断开连接的信号,关闭m_variantManager而不是断开连接,并在相关的插槽中添加qDebug() - 当您断开连接时发出一些无赖信号。

编辑: 由于您自己实现插槽,您可以随时有一个标志,并检查它在PropertyBrowser :: valueChanged然后只是忽略信号。

不知m_variantManager->方法addProperty()(从的setSelected(称)不immidiately设置的值,或设置他们,但排队的更新,然后你在objectUpdated()断开导致这些事件被丢弃。

+0

使用'm_variantManager-> blockSignals'似乎与我所期望的断开/重新连接具有完全相同的效果,尽管它确实为更好的代码。**我是**没有连接任何其他的m_variantManager,但也许你'还有其他的东西是不经意的......也许我可以用SignalSpy或者其他东西来找出它是什么,明天我就得试试,谢谢。否则,不要发送'valueChanged'信号来阻止m_variantManager,我可以防止对象暂时收到它吗? – mpen 2009-08-25 07:49:44

+0

“尝试di只连接你连接的信号“ - 做到了。没有意识到你可以通过更多的参数'断开连接',仍然是新的Qt :)仍然不知道是什么原因导致了这种行为,但哦... – mpen 2009-08-26 19:50:58

+0

看起来像一些其他信号连接到“this”从m_variantManager,可能在构造函数中:new QtVariantPropertyManager(this)。 – Eugene 2009-08-27 03:26:12