Странная ошибка Qt (связана с редактором свойств) - PullRequest
0 голосов
/ 25 августа 2009

Немного относится к этому вопросу , но вам не нужно его читать. Скриншот полезен, хотя:

image

So what's happening is when you click an object, change a property, deselect it and then reselect it, the property editor will be reset to all 0s, even though those aren't the actual values. When you actually click in the text boxes in the editor, the correct value appears. Does that mean it's just a display issue or what? How come the editor has two different values? This only happens when the highlighted lines (with arrows) are left intact -- if they are commented out, this won't occur. The code:

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)));  // 

However, I need those lines because they prevent setValue from triggering a valueChanged signal which causes other issues. This seems to indicate that calls this function fixes the issue:

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);
        }
    }
}

But the only thing that THAT function does is update the actual object... it has nothing to do with the property editor (or shouldn't). Here's the entire class if you need it:

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

#include 
#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 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)), // 

It's otherwise a very cool class if you want to use it. Let's you edit the properties of any QObject given that they have Q_PROPERTYs attached.

Relevant class: http://qt.nokia.com/products/appdev/add-on-products/catalog/4/Widgets/qtpropertybrowser/

1 Ответ

2 голосов
/ 25 августа 2009

Вы подключаете что-нибудь еще к m_variantManager? Отключение линии отключит все от «этого», но вы подключите обратно только один слот.

Не уверен, что это что-то исправит, но вы можете остановить сигналы на одном объекте, используя object-> blockSignals (true). Это закроет объект, пока вы не вызовете функцию со значением false.

Попробуйте отключить только тот сигнал, который вы подключили, закрыв m_variantManager вместо отключения, и добавив qDebug () в соответствующие слоты - при отключении появляется какой-то мошеннический сигнал.

EDIT: Поскольку вы реализуете слот самостоятельно, вы всегда можете иметь флаг и проверять его в PropertyBrowser :: valueChanged, а затем просто игнорировать сигнал.

Интересно, если m_variantManager-> addProperty () (вызванный из setSelected () не устанавливает значения не сразу или устанавливает их, а ставит в очередь обновления. Тогда ваше отключение в objectUpdated () приводит к тому, что эти события отбрасываются.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...