在父级中公开子级属性

时间:2011-08-29 17:09:14

标签: qt properties pyqt designer

我想创建一个包含QSpinBox的自定义窗口小部件。我希望自定义小部件将QSpinBox的一些属性公开为自己的属性,以便它可以在Designer中方便地工作。

有没有一种方便的方法在Qt中进行这种属性代理?

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

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

3 个答案:

答案 0 :(得分:1)

Alrite,所以这是一种方法。

这比为每个属性手动编写函数要好。基本上,您编写了一个为您扩展代码的宏。 我的widget中有一个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_

答案 1 :(得分:1)

这是一个受blueskin启发的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

答案 2 :(得分:0)

所以为了让事情变得清晰,

  1. 您将在设计器中使用此自定义小部件。
  2. 您需要自定义窗口小部件具有将QSpinBox属性公开为窗口小部件属性的属性
  3. 所以,

      

    基本上你想在自定义小部件中创建一个属性   使用'Q_PROPERTY'并使用setter和getter方法来改变   QSpinBox的属性我希望这个例子有所帮助   http://doc.qt.nokia.com/latest/properties.html#a-simple-example