2011-08-29 84 views
0

我想创建一个包含QSpinBox的自定义控件。我想让自定义小部件公开一些QSpinBox属性作为自己的属性,以便它可以在Designer中方便地使用。在父项中暴露子项的属性

有没有一种方便的方式来做这种属性代理在Qt?

我想重申,我的自定义小部件和QSpinBox之间的关系是包含,而不是继承。我正在使用pyqt,但会高兴地接受一个纯粹的qt答案。

为了澄清,我想创建具有一些额外装饰的标准小部件的变体。例如,我将添加一个可切换的图标以坐在我的QSpinBox旁边。但是我仍然希望能够在设计器中配置QSpinBox(即设置后缀,上限和下限,增量等)。

回答

1

Alrite,所以这里有一个办法。

这比为每个属性手动编写函数要好。基本上,你写一个宏来扩展你的代码。 我有一个doubleSpinBox在我的小部件中,并且每当我改变属性时它的值都会改变。并且,只要属性发生更改,就会发出一个信号,该信号连接到doubleSpinBox-> setValue()。测试和完美的作品。 完整代码在此link

#ifndef MYWIDGET_H_ 
#define MYWIDGET_H_ 

#include <QtGui/QWidget> 
#include <QtGui/QLabel> 
#include "ui_mywidgetform.h" 

#define MYPROPERTY_SET_FUNC(_PROPCLASS_, _PROP_PARAM_NAME_, _PROP_SET_FUNC_NAME_, _PROP_NOTIFY_) \ 
    void _PROP_SET_FUNC_NAME_(_PROPCLASS_ _PROP_PARAM_NAME_) \ 
    { \ 
    emit _PROP_NOTIFY_(_PROP_PARAM_NAME_); \ 
    } 

#define MYPROPERTY_GET_FUNC(_PROPCLASS_, _PROP_READ_FUNC_NAME_, _PROP_VARIABLE_)\ 
    _PROPCLASS_ _PROP_READ_FUNC_NAME_() const \ 
    { return _PROP_VARIABLE_; } 

class MyWidget : public QWidget 
{ 
    Q_OBJECT 

public: 
    MyWidget(QWidget *parent = 0); 
    ~MyWidget(); 
    enum Accuracy {Good, Bad}; 

signals: 
    void doubleSpinBoxValueChanged(double); 
    void accuracyChanged(Accuracy); 

private: 
    Q_PROPERTY(Accuracy accuracy READ accuracy WRITE setAccuracy NOTIFY accuracyChanged) 
    Q_PROPERTY(double doubleSpinBoxValue READ doubleSpinBoxValue WRITE setDoubleSpinBoxValue) 

private: 
    Accuracy m_accuracy; //custom class property 
    Ui::Form m_ui; 

public: 
    //Getter functions 
    MYPROPERTY_GET_FUNC (double, doubleSpinBoxValue, m_ui.doubleSpinBox->value()) 
    MYPROPERTY_GET_FUNC (Accuracy, accuracy, m_accuracy) 
    //Setter functions 
    MYPROPERTY_SET_FUNC(Accuracy, accuracy, setAccuracy, accuracyChanged) 
    MYPROPERTY_SET_FUNC(double, doubleSpinBoxValue, setDoubleSpinBoxValue, doubleSpinBoxValueChanged) 

}; 

#endif // MYWIDGET_H_ 
0

因此,为了使事情有点清楚,

  1. 您将使用在设计这个自定义部件。
  2. 您需要自定义部件有暴露QSpinBox性能作为窗口小部件的属性

所以性能,

基本上你会想用“Q_PROPERTY”来创建自定义窗口小部件 属性并使用setter和getter方法来更改QSpinBox的属性 我希望此示例能够帮助 http://doc.qt.nokia.com/latest/properties.html#a-simple-example

+0

我在寻找的东西更加自动化。我将制作包含许多基本小部件类型的自定义小部件,并且每个小部件都将有许多属性进行代理。以手动方式代理每个属性会很容易出错并且很费力。 – goertzenator

+0

好..明白,为什么你想要子窗口小部件的属性作为主窗口小部件的属性?如果您已经将自定义小部件作为Qt-Designer插件,那么您应该可以设置/获取所有子小部件的属性 – blueskin

+0

我有一个包含QCheckBox和QSpinBox的自定义小部件运行(从QWidget派生)。在Designer中我看不到编辑子小部件属性的方法。 – goertzenator

1

这是一个受布鲁斯金启发的PyQt版本。这里主要的操作差异是自定义窗口小部件类在运行时而不是编译时组成。这样做的好处是我们可以以编程方式检查目标元对象并使用它来生成代理属性。

现在PyQt是从C++编译的,所以我必须相信,它也可以在运行时在C++中生成qt类型。不过,我敢打赌那将是地狱般的。

 
from PyQt4 import QtGui, QtCore 

def makeProxyProperty(childname, childtype, childpropname): 

    metaobject = childtype.staticMetaObject 
    metaproperty = metaobject.property(metaobject.indexOfProperty(childpropname)) 

    def getter(self): 
     return metaproperty.read(getattr(self, childname)) 

    def setter(self, val): 
     return metaproperty.write(getattr(self, childname), val) 

    return QtCore.pyqtProperty(metaproperty.typeName(), fget=getter, fset=setter) 


class Widget1(QtGui.QWidget): 
    def __init__(self, parent=None): 
     super().__init__(parent) 
     self.spinbox = QtGui.QSpinBox() 
     self.checkbox = QtGui.QCheckBox() 
     layout = QtGui.QHBoxLayout() 
     layout.addWidget(self.checkbox) 
     layout.addWidget(self.spinbox) 
     self.setLayout(layout) 

    spinbox_suffix = makeProxyProperty("spinbox", QtGui.QSpinBox, "suffix") 
    spinbox_prefix = makeProxyProperty("spinbox", QtGui.QSpinBox, "prefix") 
    spinbox_minimum = makeProxyProperty("spinbox", QtGui.QSpinBox, "minimum") 
    spinbox_maximum = makeProxyProperty("spinbox", QtGui.QSpinBox, "maximum") 

Widget1 in designer

+0

不错,我猜PyQt会给运行时带来更多的灵活性。我几乎没有使用它。 – blueskin