Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. General and Desktop
  4. Using a lambda in a connection
Qt 6.11 is out! See what's new in the release blog

Using a lambda in a connection

Scheduled Pinned Locked Moved Unsolved General and Desktop
5 Posts 3 Posters 1.7k Views 1 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • tomyT Offline
    tomyT Offline
    tomy
    wrote on last edited by
    #1

    Hi all,

    Please take a look at these files:

    List.h:

    #ifndef LIST_H
    #define LIST_H
    
    #include <QMainWindow>
    #include "Task.h"
    #include <QVector>
    
    class QLabel;
    class QPushButton;
    class QHBoxLayout;
    class QVBoxLayout;
    
    class List : public QMainWindow
    {
        Q_OBJECT
    
    public:
        explicit List(QWidget *parent = nullptr);
        void updateStatus();
        ~List();
    
    public slots:
        void addTask();
        void removeTask(Task*);
        void taskStatusChanged();
    
    private:
        QVector<Task*> mTasks;
        QLabel* statusLabel;
        QPushButton* addTaskButtun;
        QHBoxLayout* hBox;
        QVBoxLayout* vBox;
    };
    
    #endif // LIST_H
    

    List.cpp:

    #include "list.h"
    #include <QPushButton>
    #include <QLabel>
    #include <QHBoxLayout>
    #include <QVBoxLayout>
    #include <QString>
    #include <QInputDialog>
    #include <QLineEdit>
    
    List::List(QWidget *parent)
        : QMainWindow(parent), mTasks()
    {
        statusLabel = new QLabel(tr("Status: 0 todo / 0 done"));
        addTaskButtun = new QPushButton(tr("Add task"));
    
        hBox = new QHBoxLayout;
        hBox->addWidget(statusLabel);
        hBox->addStretch();
        hBox->addWidget(addTaskButtun);
    
        vBox = new QVBoxLayout;
        vBox->addLayout(hBox);
        vBox->addStretch();
    
        QWidget *widget = new QWidget;
        widget->setLayout(vBox);
        setCentralWidget(widget);
    
        connect(addTaskButtun, &QPushButton::clicked, this, &List::addTask);
        updateStatus();
    }
    
    //************************************************
    
    void List::addTask() {
       bool ok;
       QString name = QInputDialog::getText(this, tr("Add Task"), tr("Task name"),
                                           QLineEdit::Normal, tr("Untitled task"), &ok);
    
       if(ok && !name.isEmpty()) {
           Task* task = new Task(name);
           connect(task, &Task::statusChanged, this, &List::taskStatusChanged);
           mTasks.append(task);
           vBox->addWidget(task);
           updateStatus();
       }
    }
    
    //*********************************************
    
    void List::removeTask(Task* task) {
       mTasks.removeOne(task);
       vBox->removeWidget(task);
       delete task;
       updateStatus();
    }
    
    //**************************************
    
    void List::taskStatusChanged() {
        updateStatus();
    }
    
    //************************************
    
    void List::updateStatus() {
        int completedCount = 0;
    
        for(auto t: mTasks)
            if(t->isCompleted())
                completedCount++;
    
        int todoCount = mTasks.size() - completedCount;
        statusLabel->setText(QString("Statuse: %1 todo / %2 completed")
                                    .arg(todoCount) .arg(completedCount));
    }
    
    //*****************************
    
    List::~List()
    {
        delete vBox;
    }
    

    Task.h:

    #ifndef TASK_H
    #define TASK_H
    
    #include <QWidget>
    #include <QString>
    
    class QCheckBox;
    class QPushButton;
    class QHBoxLayout;
    
    class Task : public QWidget
    {
        Q_OBJECT
    
    public:
        explicit Task(const QString&, QWidget* parent = nullptr);
    
        void setName(const QString&);
        QString name() const;
        bool isCompleted() const;
    
        ~Task();
    
    public slots:
        void rename();
    
    signals:
       void removed(Task*);
       void statusChanged(Task*);
    
    private slots:
       void checked(bool);
    
    private:
       QCheckBox* checkbox;
       QPushButton* editButton;
       QPushButton* removeButton;
       QHBoxLayout* hBox;
    };
    
    #endif // TASK_H
    

    Task.cpp:

    #include "task.h"
    #include "list.h"
    #include <QInputDialog>
    #include <QWidget>
    #include <QHBoxLayout>
    #include <QPushButton>
    #include <QCheckBox>
    
    Task::Task(const QString& name, QWidget* parent) : QWidget (parent)
    {
        checkbox = new QCheckBox;
        editButton = new QPushButton(tr("Edit"));
        removeButton = new QPushButton(tr("Remove"));
    
        hBox = new QHBoxLayout;
        hBox->addWidget(checkbox);
        hBox->addStretch();
        hBox->addWidget(editButton);
        hBox->addWidget(removeButton);
    
        setLayout(hBox);
    
        setName(name);
    
        connect(editButton, &QPushButton::clicked, this, &Task::rename);
        connect(removeButton, &QPushButton::clicked, [this]()->void {
                    
                   &List::removeTask(this); // call the function/slot
                });
    
        connect(checkbox, &QCheckBox::toggled, this, &Task::checked);
    };
    
    //*************************************
    
    void Task::setName(const QString& name) {
        checkbox->setText(name);
    }
    
    //********************************************
    
    QString Task::name() const {
        return checkbox->text();
    }
    
    //*****************************
    
    bool Task::isCompleted() const {
        return checkbox->isChecked();
    }
    
    //****************************************
    
    void Task::rename() {
        bool ok;
        QString value = QInputDialog::getText(this, tr("Edit task"), tr("Task name"),
                                              QLineEdit::Normal, this->name(), &ok);
        if(ok && !value.isEmpty())
            setName(value);
    }
    
    //************************************
    
    void Task::checked(bool checked) {
        QFont font(checkbox->font());
        font.setStrikeOut(checked);
        checkbox->setFont(font);
    
        emit statusChanged(this);
    }
    
    //**************************************************
    
    Task::~Task() {
        delete hBox;
    }
    

    Why do I get the following error for this part please:

    connect(removeButton, &QPushButton::clicked, [this]()->void {
                   &List::removeTask(this); // call the function/slot
                });
    

    Error: Call to non-static member function without an object argument

    From my view, all the requirements are supplied, but still get this error!

    raven-worxR 1 Reply Last reply
    0
    • tomyT tomy

      Hi all,

      Please take a look at these files:

      List.h:

      #ifndef LIST_H
      #define LIST_H
      
      #include <QMainWindow>
      #include "Task.h"
      #include <QVector>
      
      class QLabel;
      class QPushButton;
      class QHBoxLayout;
      class QVBoxLayout;
      
      class List : public QMainWindow
      {
          Q_OBJECT
      
      public:
          explicit List(QWidget *parent = nullptr);
          void updateStatus();
          ~List();
      
      public slots:
          void addTask();
          void removeTask(Task*);
          void taskStatusChanged();
      
      private:
          QVector<Task*> mTasks;
          QLabel* statusLabel;
          QPushButton* addTaskButtun;
          QHBoxLayout* hBox;
          QVBoxLayout* vBox;
      };
      
      #endif // LIST_H
      

      List.cpp:

      #include "list.h"
      #include <QPushButton>
      #include <QLabel>
      #include <QHBoxLayout>
      #include <QVBoxLayout>
      #include <QString>
      #include <QInputDialog>
      #include <QLineEdit>
      
      List::List(QWidget *parent)
          : QMainWindow(parent), mTasks()
      {
          statusLabel = new QLabel(tr("Status: 0 todo / 0 done"));
          addTaskButtun = new QPushButton(tr("Add task"));
      
          hBox = new QHBoxLayout;
          hBox->addWidget(statusLabel);
          hBox->addStretch();
          hBox->addWidget(addTaskButtun);
      
          vBox = new QVBoxLayout;
          vBox->addLayout(hBox);
          vBox->addStretch();
      
          QWidget *widget = new QWidget;
          widget->setLayout(vBox);
          setCentralWidget(widget);
      
          connect(addTaskButtun, &QPushButton::clicked, this, &List::addTask);
          updateStatus();
      }
      
      //************************************************
      
      void List::addTask() {
         bool ok;
         QString name = QInputDialog::getText(this, tr("Add Task"), tr("Task name"),
                                             QLineEdit::Normal, tr("Untitled task"), &ok);
      
         if(ok && !name.isEmpty()) {
             Task* task = new Task(name);
             connect(task, &Task::statusChanged, this, &List::taskStatusChanged);
             mTasks.append(task);
             vBox->addWidget(task);
             updateStatus();
         }
      }
      
      //*********************************************
      
      void List::removeTask(Task* task) {
         mTasks.removeOne(task);
         vBox->removeWidget(task);
         delete task;
         updateStatus();
      }
      
      //**************************************
      
      void List::taskStatusChanged() {
          updateStatus();
      }
      
      //************************************
      
      void List::updateStatus() {
          int completedCount = 0;
      
          for(auto t: mTasks)
              if(t->isCompleted())
                  completedCount++;
      
          int todoCount = mTasks.size() - completedCount;
          statusLabel->setText(QString("Statuse: %1 todo / %2 completed")
                                      .arg(todoCount) .arg(completedCount));
      }
      
      //*****************************
      
      List::~List()
      {
          delete vBox;
      }
      

      Task.h:

      #ifndef TASK_H
      #define TASK_H
      
      #include <QWidget>
      #include <QString>
      
      class QCheckBox;
      class QPushButton;
      class QHBoxLayout;
      
      class Task : public QWidget
      {
          Q_OBJECT
      
      public:
          explicit Task(const QString&, QWidget* parent = nullptr);
      
          void setName(const QString&);
          QString name() const;
          bool isCompleted() const;
      
          ~Task();
      
      public slots:
          void rename();
      
      signals:
         void removed(Task*);
         void statusChanged(Task*);
      
      private slots:
         void checked(bool);
      
      private:
         QCheckBox* checkbox;
         QPushButton* editButton;
         QPushButton* removeButton;
         QHBoxLayout* hBox;
      };
      
      #endif // TASK_H
      

      Task.cpp:

      #include "task.h"
      #include "list.h"
      #include <QInputDialog>
      #include <QWidget>
      #include <QHBoxLayout>
      #include <QPushButton>
      #include <QCheckBox>
      
      Task::Task(const QString& name, QWidget* parent) : QWidget (parent)
      {
          checkbox = new QCheckBox;
          editButton = new QPushButton(tr("Edit"));
          removeButton = new QPushButton(tr("Remove"));
      
          hBox = new QHBoxLayout;
          hBox->addWidget(checkbox);
          hBox->addStretch();
          hBox->addWidget(editButton);
          hBox->addWidget(removeButton);
      
          setLayout(hBox);
      
          setName(name);
      
          connect(editButton, &QPushButton::clicked, this, &Task::rename);
          connect(removeButton, &QPushButton::clicked, [this]()->void {
                      
                     &List::removeTask(this); // call the function/slot
                  });
      
          connect(checkbox, &QCheckBox::toggled, this, &Task::checked);
      };
      
      //*************************************
      
      void Task::setName(const QString& name) {
          checkbox->setText(name);
      }
      
      //********************************************
      
      QString Task::name() const {
          return checkbox->text();
      }
      
      //*****************************
      
      bool Task::isCompleted() const {
          return checkbox->isChecked();
      }
      
      //****************************************
      
      void Task::rename() {
          bool ok;
          QString value = QInputDialog::getText(this, tr("Edit task"), tr("Task name"),
                                                QLineEdit::Normal, this->name(), &ok);
          if(ok && !value.isEmpty())
              setName(value);
      }
      
      //************************************
      
      void Task::checked(bool checked) {
          QFont font(checkbox->font());
          font.setStrikeOut(checked);
          checkbox->setFont(font);
      
          emit statusChanged(this);
      }
      
      //**************************************************
      
      Task::~Task() {
          delete hBox;
      }
      

      Why do I get the following error for this part please:

      connect(removeButton, &QPushButton::clicked, [this]()->void {
                     &List::removeTask(this); // call the function/slot
                  });
      

      Error: Call to non-static member function without an object argument

      From my view, all the requirements are supplied, but still get this error!

      raven-worxR Offline
      raven-worxR Offline
      raven-worx
      Moderators
      wrote on last edited by
      #2

      @tomy
      since removeTask() is not static (as the error says) you also need to capture an instance of List

      connect(removeButton, &QPushButton::clicked, [this,list]()->void {
                     list->removeTask(this); // call the function/slot
                  });
      

      --- SUPPORT REQUESTS VIA CHAT WILL BE IGNORED ---
      If you have a question please use the forum so others can benefit from the solution in the future

      tomyT 1 Reply Last reply
      3
      • raven-worxR raven-worx

        @tomy
        since removeTask() is not static (as the error says) you also need to capture an instance of List

        connect(removeButton, &QPushButton::clicked, [this,list]()->void {
                       list->removeTask(this); // call the function/slot
                    });
        
        tomyT Offline
        tomyT Offline
        tomy
        wrote on last edited by tomy
        #3

        @raven-worx

        You're right. Inside the lambda body, it's cpp not Qt stuff.
        However, the version above doesn't work either.
        I think I need an instance (pointer) of the class List in the header of Task as, say, list, and then inside Task.cpp it must be initialized and after that it must be used the way above.

        still

        connect(removeButton, &QPushButton::clicked, [this,list]()->void {
                       list->removeTask(this); // call the function/slot
                    });
        

        would be incorrect: list doesn't name a variable*

        And it's good:

        connect(removeButton, &QPushButton::clicked, [this]()->void {
                       list->removeTask(this); // call the function/slot
                    });
        
        jsulmJ 1 Reply Last reply
        0
        • tomyT tomy

          @raven-worx

          You're right. Inside the lambda body, it's cpp not Qt stuff.
          However, the version above doesn't work either.
          I think I need an instance (pointer) of the class List in the header of Task as, say, list, and then inside Task.cpp it must be initialized and after that it must be used the way above.

          still

          connect(removeButton, &QPushButton::clicked, [this,list]()->void {
                         list->removeTask(this); // call the function/slot
                      });
          

          would be incorrect: list doesn't name a variable*

          And it's good:

          connect(removeButton, &QPushButton::clicked, [this]()->void {
                         list->removeTask(this); // call the function/slot
                      });
          
          jsulmJ Offline
          jsulmJ Offline
          jsulm
          Lifetime Qt Champion
          wrote on last edited by
          #4

          @tomy said in Using a lambda in a connection:

          I think I need an instance (pointer) of the class List

          Of course you need - that's what @raven-worx told you. If there is no variable/member named "list" the suggested solution cannot work...

          https://forum.qt.io/topic/113070/qt-code-of-conduct

          1 Reply Last reply
          2
          • tomyT Offline
            tomyT Offline
            tomy
            wrote on last edited by
            #5
            This post is deleted!
            1 Reply Last reply
            0

            • Login

            • Login or register to search.
            • First post
              Last post
            0
            • Categories
            • Recent
            • Tags
            • Popular
            • Users
            • Groups
            • Search
            • Get Qt Extensions
            • Unsolved