Qt:连接QObject类中定义的类的插槽

时间:2017-05-20 03:51:40

标签: c++ qt qt-signals

我有一个类MainWindow,它将包含几个带有自己的标题和其他成员的QWidgetTable。现在,我想在类MainWindow中定义自定义表类,因为它们非常简单。见下面的例子:

class MainWindow : public QMainWindow
{
    Q_OBJECT
public:
    explicit MainWindow(SSHClient &client, QWidget *parent = 0);

public slots:
    struct Workflow_Table {
        QTableWidget* widget;
        QStandardItemModel model;
        QStringList headers;

        void addRow(){}
        void removeRow(){}
    } workflow_table;


private:
    SSHClient& client;
    Ui::MainWindow* ui;

    CTL ctl;
};

Ui::MainWindow内我有QPushButtons来添加和删除workflow_table的行。我想将这些QPushButton::clicked信号连接到 MainWindow::Workflow_Table::addRow,但我没有取得任何成功,也不知道我尝试的是否可行。

MainWindow::MainWindow(SSHClient &client, QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow),
    client(client)
{
    ui->setupUi(this);

    //class CTL is a not a QObject class, yet std::bind causes it to act like a slot here. This statement compiles and runs fine.
    connect(ui->button_load_ctl, &QPushButton::clicked, this, std::bind(&CTL::saveas, &ctl, "saved.ctl"));

    //Error: 3 Arguments provided - 4 Expected. I'm almost certain this won't work.
    connect(ui->button_add, &QPushButton::clicked, this, &MainWindow::Workflow_Table::addRow);

    //Error: Not a signal or slot declaration. Not sure why this isn't working.
    connect(ui->button_add, &QPushButton::clicked, this, std::bind(&MainWindow::Workflow_Table::addRow, &workflow_table));

    //This doesn't work either. Error 1.
    connect(ui->button_add, &QPushButton::clicked, this, std::bind(&Workflow_Table::addRow, &workflow_table));

}

我是否可以将MainWindow::Workflow_Table::addRow(不将Workflow_Table作为QObject)连接到来自MainWindow的QPushButton::clicked信号?

简单的解决方案是使Workflow_Table成为QObject,但我很好奇我是否仍然可以连接Workflow_Table的函数,因为它们是在QObject的范围内定义的。我已经能够使用std :: bind连接其他非槽函数,就像CTL::saveas函数一样,所以我认为我可以在这里做类似的事情。我还尝试在Workflow_Tablepublic访问说明符下移动public slots,但两者都没有效果。

1 个答案:

答案 0 :(得分:-1)

一切正常 - 因为没有显示失败的实际完整示例,这是你的错。当我将其粘贴到一个空项目中时,除了第二个connect之外,所有内容都会编译,你必须使用std::bind或lambda,以便addRow()能够使用它。

一般来说,如果lambda会更短,那么使用bind是没有意义的,所以只要在代码清晰度得到它时就使用lambdas。

这有效:

// https://github.com/KubaO/stackoverflown/tree/master/questions/connect-bind-44081724
#include <QtWidgets>
#include <functional>

class Class : public QWidget
{
   Q_OBJECT
   QPushButton button;
   struct CTL {
      void saveas(const QString &);
   } ctl;
   struct Workflow_Table {
       void addRow() {}
   } workflow_table;

public:
   Class() {
      connect(&button, &QPushButton::clicked, this, std::bind(&CTL::saveas, &ctl, "saved.ctl"));
      connect(&button, &QPushButton::clicked, this, [this]{ workflow_table.addRow(); });
      connect(&button, &QPushButton::clicked, this, std::bind(&Workflow_Table::addRow, &workflow_table));

      // better yet
      connect(&button, &QPushButton::clicked, this, [this]{ ctl.saveas("saved.ctl"); });
      connect(&button, &QPushButton::clicked, this, [this]{ workflow_table.addRow(); });

      // or simply, if we know that `this` will outlive `button` (they do by design here),
      // and that both button and this live in the same thread (again, they do by design here)
      connect(&button, &QPushButton::clicked, [this]{ ctl.saveas("saved.ctl"); });
      connect(&button, &QPushButton::clicked, [this]{ workflow_table.addRow(); });
   }
};

int main() {}
#include "main.moc"