奇怪的Qt bug(与属性编辑器有关)

时间:2009-08-25 02:23:43

标签: qt

this question略有关系,但你真的不需要阅读。截图有用:

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

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_PROPERTY。

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

1 个答案:

答案 0 :(得分:2)

您是否将其他任何内容连接到m_variantManager?断开线路将断开与“this”的所有连接,但您只能连接回一个插槽。

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

尝试仅断开连接的信号,关闭m_variantManager而不是断开连接,并在相关的插槽中添加qDebug() - 当你断开它时会发出一些恶意信号。

编辑: 由于您自己实现了插槽,因此您可以始终使用标志并在PropertyBrowser :: valueChanged中进行检查,然后忽略该信号。

我想知道m_variantManager-&gt; addProperty()(从setSelected()调用不会立即设置值,或者设置它们但是队列更新。然后你在objectUpdated()中断开连接会导致这些事件被丢弃。