【问题标题】:Qt: Connect slot for a class defined within a QObject classQt:在 QObject 类中定义的类的连接槽
【发布时间】:2017-05-20 03:51:39
【问题描述】:

我有类MainWindow,它将包含几个QWidgetTables,它们有自己的标题和其他成员。现在,我想在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_Table 移动到publicpublic slots 访问说明符下,但都没有奏效。

【问题讨论】:

  • 最简单的方法是将addRow() 放入onPushButton_clicked()。使用元对象系统对于单击和添加行来说是相当大的。

标签: c++ qt qt-signals


【解决方案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"

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2014-01-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多