C ++ Qt,传递回调

问题描述 投票:3回答:1

编辑#2:想出我需要的lambda调用语法!

[=](int value) { (this->*callback_function)(i, value); }

仍在寻找关于如何更好地协调这项任务的建议......这似乎太乱了。


编辑:更新的代码,几乎在那里,但仍然遇到了障碍。

template <typename F>
void Dialog::create_spinbox_column(const int &NUM_ROWS, QFrame *&frame,
                                   QLabel *label_arr[],
                                   QSpinBox *spinbox_arr[],
                                   F callback_function) {
    frame = new QFrame();
    QGridLayout *layout = new QGridLayout;
    for(int i = 0; i < NUM_ROWS; i++) {
        int row = i+1;
        QString label_text = QObject::tr("Line %1:").arg(row);
        label_arr[i] = new QLabel(label_text);
        spinbox_arr[i] = new QSpinBox;
        layout->addWidget(label_arr[i], row, 1);
        layout->addWidget(spinbox_arr[i], row, 2);
        QObject::connect(spinbox_arr[i], qOverload<int>(&QSpinBox::valueChanged), this,
                        [=](int value) { callback_function(i, value); } );
    }
    frame->setLayout(layout);
}

我收到了一个错误

error: must use '.*' or '->*' to call pointer-to-member function in 'callback_function (...)', e.g. '(... ->* callback_function) (...)'
                         [=](int value) { callback_function(i, value); } );
                                                       ^

我尝试了一些像this->callback_function(i, value)这样的东西,但我尝试过的任何东西都没有用过。我绝对不希望回调是静态的,这没有意义,它应该在当前Dialog类的上下文中调用,该类调用create_spinbox_column函数。


以下是原帖:


我最近开始使用Qt将我的一个程序从基于文本的输入转换为GUI输入,但我遇到了一些障碍。我可以在Qt中使用如何“正确”执行此操作的高级设计反馈,以及如何调试当前问题的具体反馈。

首先,快速描述我当前的任务(如果你不在乎,直接跳到下面我的代码):我将有大量的旋转盒,我想整齐地组织并连接到void callback_with_id(int id, int value)形式的回调函数,其中id将是一个唯一的数字,用于识别哪个旋转框的值发生了变化,而value当然是该旋转框的新值。

我设法创建了一个我喜欢的视觉布局,但是尝试将spinbox连接到回调函数会给我带来麻烦。这是我的代码,目前无法编译。随时可以假装ACCOUNT_DATA_COLS = 1

void Dialog::create_spinbox_column(const int &NUM_ROWS, QFrame *&frame,
                                   QLabel **label_arr,
                                   QSpinBox **spinbox_arr,
                                   void (*callback_function)(int, int)) {
    frame = new QFrame();
    QGridLayout *layout = new QGridLayout;
    for(int i = 0; i < NUM_ROWS; i++) {
        int row = i+1;
        QString label_text = QObject::tr("Line %1:").arg(row);
        label_arr[i] = new QLabel(label_text);
        spinbox_arr[i] = new QSpinBox;
        layout->addWidget(label_arr[i], row, 1);
        layout->addWidget(spinbox_arr[i], row, 2);
        //QObject::connect(spinbox_arr[i], SIGNAL(valueChanged(int)), this,
        //                [=](int value) { callback_function(i, value); };
    }
    frame->setLayout(layout);
}

(我注释掉了连接线,因为我收到了编译错误。)

void Dialog::create_account_data_grid() {
    account_data_box = new QGroupBox(tr("Account Data"));
    QHBoxLayout *layout = new QHBoxLayout;
    for (int i = 0; i < ACCOUNT_DATA_COLS; i++) {
        QFrame *frame;
        QLabel *label_arr[ACCOUNT_DATA_ROWS];
        QLabel *spinbox_arr[ACCOUNT_DATA_ROWS];
        create_spinbox_column(ACCOUNT_DATA_ROWS, frame, label_arr, spinbox_arr,
                              callback_with_id);
        // int col = i + 1;
        layout->addWidget(frame);
    }
    account_data_box->setLayout(layout);
}

和我的回调函数:

void Dialog::callback_with_id(int id, int value) {
    std::cout << "callback_with_id(" << value << ", " << id << ")" << std::endl;
}

我收到了错误

error: no matching function for call to 'Dialog::create_spinbox_column(const int&, QFrame*&, QLabel* [8], QLabel* [8], <unresolved overloaded function type>)'
                               callback_with_id);
                                               ^

我敢肯定我在这里做的不仅仅是一件事,对任何反馈都会感激不尽。

c++ qt
1个回答
3
投票

注释行的问题是你混合了两种不同类型的连接:“运行时”(使用SIGNALSLOT宏)和“编译时”(允许你直接传递可调用的那个)。

通常后者的语法是

QObject::connect(spinbox_arr[i], &QSpinBox::someSignal, this,
                [=](int value) { callback_function(i, value); };

但你不能直接为valueChanged信号做这个,因为它有两个重载,因此你必须使用qOverload,所以结果代码看起来像这样:

QObject::connect(spinbox_arr[i], qOverload<int>(&QSpinBox::valueChanged), this,
                [=](int value) { callback_function(i, value); };

这需要一些C ++ 14支持。如果你没有它,那么你必须使用QOverload<int>::of(&QSpinBox::valueChanged)

另外,正如评论中指出的那样,请确保:

  1. callback_with_id是一个静态函数,
  2. 或者使create_spinbox_column模仿仿函数类型,
  3. 或者只是将create_spinbox_column的最后一个参数更改为std::function<void(int, int)>并在呼叫站点传递lambda捕获this

如果您希望我详细说明这些要点,请告诉我们!

© www.soinside.com 2019 - 2024. All rights reserved.