【问题标题】:How to make the signals of child widgets inside a custom widget connectable?如何使自定义小部件内的子小部件的信号可连接?
【发布时间】:2018-09-09 19:32:21
【问题描述】:

我认为我对一个对我来说似乎很基本的概念有一些重大问题。

我创建了一个自定义小部件,它实际上只是一个小部件集合,因此会出现多次。

class CustomWidget : public QWidget {
    Q_OBJECT
public:
    explicit CustomWidget(QWidget parent=nullptr) : QWidget(parent) {
        spinboxA = new QSpinBox;
        spinboxB = new QSpinBox;
        QHBoxLayout* layout = new QHBoxLayout(this);
        layout.addWidget(spinboxA);
        layout.addWidget(spinboxB);
        this->setLayout(layout);
    }
private:
    QSpinBox* spinboxA;
    QSpinBox* spinboxB;
};

然后在 gui 中使用此自定义小部件。当然,我希望这个 gui 对旋转框值的变化做出反应。据我了解,我可以

1) 为QSpinBoxes 提供getter 并在类外连接它们的信号。 2)“重新路由”他们的信号,如下例所示

@1) 我猜是通过connect(customwidget->getSpinboxA(),SIGNAL(valueChanged(int)),this,SLOT(doSomething(int))); 使用的?

@2)

class CustomWidget : public QWidget {
    Q_OBJECT
public:
    explicit CustomWidget(QWidget parent=nullptr) : QWidget(parent) {
        spinboxA = new QSpinBox;
        spinboxB = new QSpinBox;
        QHBoxLayout* layout = new QHBoxLayout;
        layout.addWidget(spinboxA);
        layout.addWidget(spinboxB);
        this->setLayout(layout);
        connect(spinboxA,SIGNAL(valueChanged(int)),//...
            this,SLOT(onSpinboxAValueChanged(int)));
    }
private:
    QSpinBox* spinboxA;
    QSpinBox* spinboxB;
private slots:
    void onSpinboxAValueChanged(int x) {emit spinboxAValueChanged(x);}
    //...
signals:
    void spinboxAValueChanged(int x)
};

在 gui 类中可以connect(customwidget,SIGNAL(spinboxAValueChanged(int),this,SLOT(doSomething(int)));

尤其是版本 2) 看起来非常混乱,而且...我在问自己 - 如何连接到自定义小部件内的小部件的信号?

【问题讨论】:

    标签: c++ qt qt5 qt-signals custom-widgets


    【解决方案1】:

    CustomWidget 应该是模块化的,也就是说,它应该像一个黑匣子,应该在其中建立输入并获得输出,所以对我来说第二个解决方案非常接近它,但我看到了一些可以改进的地方:不必只创建一个槽来发出信号,信号可以连接到其他信号,我也建议使用新的连接语法。

    #include <QApplication>
    #include <QHBoxLayout>
    #include <QSpinBox>
    #include <QWidget>
    
    #include <QDebug>
    
    class CustomWidget : public QWidget {
        Q_OBJECT
    public:
        explicit CustomWidget(QWidget *parent =nullptr):
            QWidget(parent),
            spinboxA(new QSpinBox),
            spinboxB(new QSpinBox)
        {
            QHBoxLayout* layout = new QHBoxLayout(this);
            layout->addWidget(spinboxA);
            layout->addWidget(spinboxB);
            connect(spinboxA, QOverload<int>::of(&QSpinBox::valueChanged), this, &CustomWidget::spinboxAValueChanged);
            connect(spinboxB, QOverload<int>::of(&QSpinBox::valueChanged), this, &CustomWidget::spinboxBValueChanged);
            // old syntax:
            // connect(spinboxA, SIGNAL(valueChanged(int)), this, SIGNAL(spinboxAValueChanged(int)));
            // connect(spinboxB, SIGNAL(valueChanged(int)), this, SIGNAL(spinboxBValueChanged(int)));
        }
    private:
        QSpinBox *spinboxA;
        QSpinBox *spinboxB;
    signals:
        void spinboxAValueChanged(int x);
        void spinboxBValueChanged(int x);
    };
    
    int main(int argc, char *argv[])
    {
        QApplication a(argc, argv);
        CustomWidget w;
    
        QObject::connect(&w, &CustomWidget::spinboxAValueChanged, [](int i){
           qDebug()<< "spinboxAValueChanged: "<< i;
        });
        QObject::connect(&w, &CustomWidget::spinboxBValueChanged, [](int i){
           qDebug()<< "spinboxBValueChanged: "<< i;
        });
    
        w.show();
    
        return a.exec();
    }
    
    #include "main.moc"
    

    【讨论】:

    • 谢谢!你会如何用旧的语法来做呢?只是为了语法知识的完整性? :)
    • 啊...其实很简单,谢谢。为什么推荐新语法?
    • 仅通知 API 很难使用:您几乎总是会得到一些缓存值的代码。因此,除了通知者之外,还应该有一个 getter。我会更进一步,将这些值声明为属性(使用Q_PROPERTY),以清楚地表明存在具有可用通知和获取器的只读值。这表明了人类维护者的意图,并使得从脚本语言(包括 Qt 自己的 javascript 引擎)中使用类变得容易。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2022-01-03
    • 2013-07-22
    • 1970-01-01
    • 2014-09-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多