开发者

Exposing child's properties in the parent

I want to create a custom widget that contains a QSpinBox. I want the custom widget to expose some of QSpinBox's properties as its own so it can work conveniently in Designer.

Is there a convenient way to do this kind of property proxying in Qt?

I want to reiterate that the relationship between my custom widget and the QSpinBox is containment, not inheritan开发者_运维知识库ce. I am using pyqt, but will happily accept a pure qt answer.

To clarify, I want to create variations of standard widgets that have some extra decorations. For example, I will be adding a toggleable icon to sit beside my QSpinBox. However I still want to be able to configure the QSpinBox in designer (ie, set the suffix, upper and lower limits, increment, etc).


Alrite, so here's a way to do it.

It's better than writing a function manually for each property. Basically, you write a macro that expands the code for you. I have a doubleSpinBox in my widget and its value is changed whenever I change the property. And you emit a signal whenever the property changes, which is connected to the doubleSpinBox->setValue(). Tested and works perfectly. Complete code at this 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_


Here is a PyQt version inspired by blueskin. The main operational difference here is that the custom widget class is composed at runtime rather than compile time. The advantage to this is that we can programmatically inspect the target metaobject and use that to generate the proxy properties.

Now PyQt is compiled from c++, so I have to believe that it is also possible to generate qt types at runtime in c++. I am betting that would be hellish, however.

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")

Exposing child's properties in the parent


So to make things a bit clear,

  1. you will be using this custom widget in the designer.
  2. You need the custom widget to have properties that expose QSpinBox properties as the widget's properties

So,

basically you would want to create a property in your custom widget using 'Q_PROPERTY' and use setter and getter methods to change the QSpinBox's properties I hope this example would help http://doc.qt.nokia.com/latest/properties.html#a-simple-example

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜