2009-08-25 112 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