在父级中公开子级的属性

发布于 2024-12-01 17:24:17 字数 304 浏览 7 评论 0原文

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

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

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

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

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 inheritance. 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).

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

萌辣 2024-12-08 17:24:17

Alrite,这是一种方法。

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

#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_

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_
于我来说 2024-12-08 17:24:17

这是受 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

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

Widget1 in designer

蒗幽 2024-12-08 17:24:17

因此,为了让事情变得更清楚,

  1. 您将在设计器中使用这个自定义小部件。
  2. 您需要自定义小部件具有将 QSpinBox 属性公开为小部件属性的属性

所以,

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

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

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文