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. Destructor called twoice

Destructor called twoice

Scheduled Pinned Locked Moved Solved General and Desktop
6 Posts 3 Posters 1.9k Views
  • 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.
  • apalomerA Offline
    apalomerA Offline
    apalomer
    wrote on last edited by
    #1

    Hi all!

    I am developing a Qt application. This application consists of several widgets, one of which I want to be able to remove from the layout with a call from an action in a context menu. The widget that I created has a signal that is emitted when there is a request to delete the custom widget that I created. Then, the main application is connected to this signal and removes the widget from the layout. The problem is that, when I emmit this signal by pressing a push button of my custom widget the signal is emmited and the custom widget is propperly removed. However, when I emit the same signal from the action of the context menu, the destructor of my custom widget is called two times. Here is a simplified example of what i want to do.

    The custom widget looks like:

    #ifndef BUTTON_H
    #define BUTTON_H
    
    #include <QWidget>
    
    namespace Ui {
    class Button;
    }
    
    class Button : public QWidget
    {
        Q_OBJECT
    
    public:
        explicit Button(int n, QWidget *parent = 0);
        ~Button();
    
    private slots:
        void on_pushButton_clicked();
        void on_actionRemove_triggered();
    
    signals:
        void remove(Button* button);
    private:
        Ui::Button *ui;
    };
    
    #endif // BUTTON_H
    
    
    
    #include "button.h"
    #include "ui_button.h"
    
    Button::Button(int n, QWidget *parent) :
        QWidget(parent),
        ui(new Ui::Button)
    {
        ui->setupUi(this);
        ui->pushButton->setText("Remove button "+QString::number(n));
        addAction(ui->actionRemove);
    }
    
    Button::~Button()
    {
        delete ui;
    }
    
    void Button::on_pushButton_clicked()
    {
        emit remove(this);
    }
    
    void Button::on_actionRemove_triggered()
    {
        emit remove(this);
    }
    

    The main application looks like:

    #ifndef BUTTONSTACK_H
    #define BUTTONSTACK_H
    
    #include <QWidget>
    #include "button.h"
    
    namespace Ui {
    class ButtonStack;
    }
    
    class ButtonStack : public QWidget
    {
        Q_OBJECT
    
    public:
        explicit ButtonStack(QWidget *parent = 0);
        ~ButtonStack();
    
    private slots:
        void on_addButton_clicked();
        void remove(Button* button);
    
    private:
        Ui::ButtonStack *ui;
        int total_buttons;
    };
    
    #endif // BUTTONSTACK_H
    
    #include "buttonstack.h"
    #include "ui_buttonstack.h"
    
    ButtonStack::ButtonStack(QWidget *parent) :
        QWidget(parent),total_buttons(0),
        ui(new Ui::ButtonStack)
    {
        ui->setupUi(this);
    }
    
    ButtonStack::~ButtonStack()
    {
        delete ui;
    }
    
    void ButtonStack::on_addButton_clicked()
    {
        Button* button(new Button(total_buttons++));
        ui->qvboxlayout->insertWidget(0,button);
        connect(button,SIGNAL(remove(Button*)),this,SLOT(remove(Button*)));
    }
    
    void ButtonStack::remove(Button* button)
    {
        ui->qvboxlayout->removeWidget(button);
        delete button;
    }
    

    And the main is here:

    #include <QtGui/QApplication>
    #include "buttonstack.h"
    
    int main(int argc, char** argv)
    {
    
        QApplication app (argc, argv);
        ButtonStack bs;
        bs.show();
        return app.exec();
    }
    
    1 Reply Last reply
    0
    • C Offline
      C Offline
      Charlie_Hdz
      wrote on last edited by
      #2

      Hi @apalomer ,

      Have you tried to call the same slot in both cases?

      Would you like to try to call a reference instead that a pointer?

      Thanks

      Kind Regards,
      Enrique Hernandez
      gearstech.com.mx
      chernandez@gearstech.com.mx

      1 Reply Last reply
      0
      • SGaistS Offline
        SGaistS Offline
        SGaist
        Lifetime Qt Champion
        wrote on last edited by
        #3

        Hi,

        So you are right clicking on the button to get the menu ? So you are likely sending the signal twice.

        Interested in AI ? www.idiap.ch
        Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

        1 Reply Last reply
        0
        • apalomerA Offline
          apalomerA Offline
          apalomer
          wrote on last edited by
          #4

          Hi,
          thank you for your replies.

          @Charlie_Hdz I have tried what you suggest. I've changed my custom widget so that in both cases (the button click and the action triggered) the same slot is called. This is how the new custom widget looks like:

          #ifndef BUTTON_H
          #define BUTTON_H
          
          #include <QWidget>
          
          namespace Ui {
          class Button;
          }
          
          class Button : public QWidget
          {
              Q_OBJECT
          
          public:
              explicit Button(int n, QWidget *parent = 0);
              ~Button();
          
          private slots:
              void removeRequested();
          
          signals:
              void remove(Button* button);
          private:
              Ui::Button *ui;
          };
          
          #endif // BUTTON_H
          
          #include "button.h"
          #include "ui_button.h"
          
          Button::Button(int n, QWidget *parent) :
              QWidget(parent),
              ui(new Ui::Button)
          {
              ui->setupUi(this);
              ui->pushButton->setText("Remove button "+QString::number(n));
              addAction(ui->actionRemove);
              connect(ui->actionRemove,SIGNAL(triggered()),this,SLOT(removeRequested()));
              connect(ui->pushButton,SIGNAL(clicked()),this,SLOT(removeRequested()));
          }
          
          Button::~Button()
          {
              delete ui;
          }
          
          void Button::removeRequested()
          {
              emit remove(this);
          }
          

          The same thing happens.

          @SGaist I have also tried (with this new code) what happens if I right click the button when it does not have a context menu. The Slot is not called at any time, so I think the problem does not come from emitting twice the same signal. Instead, I believe that the problem is because in the destructor of my custom widget the line

          delete ui;
          

          actually calls again the destructor of the class. This might be because it has to destroy the context menu as well? But I am not sure if this happens because of the destruction of the context menu or not, it is just my guess.

          Any new ideas on what could I do?

          1 Reply Last reply
          0
          • apalomerA Offline
            apalomerA Offline
            apalomer
            wrote on last edited by
            #5

            Hello,
            I have found the solution. Now, instead of directly deleting the widget I use deleteLater() so the widget is scheduled to be destroyed when the control returns to the event loop. The final code can be found here and it looks like:

            Custom widget:

            #ifndef BUTTON_H
            #define BUTTON_H
            
            #include <QWidget>
            
            namespace Ui {
            class Button;
            }
            
            class Button : public QWidget
            {
                Q_OBJECT
            
            public:
                explicit Button(int n, QWidget *parent = 0);
                ~Button();
            
            private slots:
                void removeRequested();
            
            signals:
                void remove(Button* button);
            private:
                Ui::Button *ui;
            };
            
            #endif // BUTTON_H
            
            #include "button.h"
            #include "ui_button.h"
            
            Button::Button(int n, QWidget *parent) :
                QWidget(parent),
                ui(new Ui::Button)
            {
                ui->setupUi(this);
                ui->pushButton->setText("Remove button "+QString::number(n));
                addAction(ui->actionRemove);
                connect(ui->actionRemove,SIGNAL(triggered()),this,SLOT(removeRequested()));
                connect(ui->pushButton,SIGNAL(clicked()),this,SLOT(removeRequested()));
            }
            
            Button::~Button()
            {
                delete ui;
            }
            
            void Button::removeRequested()
            {
                emit remove(this);
            }
            

            Main gui:

            #ifndef BUTTONSTACK_H
            #define BUTTONSTACK_H
            
            #include <QWidget>
            #include "button.h"
            
            namespace Ui {
            class ButtonStack;
            }
            
            class ButtonStack : public QWidget
            {
                Q_OBJECT
            
            public:
                explicit ButtonStack(QWidget *parent = 0);
                ~ButtonStack();
            
            private slots:
                void on_addButton_clicked();
                void remove(Button* button);
            
            private:
                Ui::ButtonStack *ui;
                int total_buttons;
            };
            
            #endif // BUTTONSTACK_H
            
            #include "buttonstack.h"
            #include "ui_buttonstack.h"
            
            ButtonStack::ButtonStack(QWidget *parent) :
                QWidget(parent),total_buttons(0),
                ui(new Ui::ButtonStack)
            {
                ui->setupUi(this);
            }
            
            ButtonStack::~ButtonStack()
            {
                delete ui;
            }
            
            void ButtonStack::on_addButton_clicked()
            {
                Button* button(new Button(total_buttons++));
                ui->qvboxlayout->insertWidget(0,button);
                connect(button,SIGNAL(remove(Button*)),this,SLOT(remove(Button*)));
            }
            
            void ButtonStack::remove(Button* button)
            {
                ui->qvboxlayout->removeWidget(button);
                button->deleteLater();
            }
            

            Main:

            #include <QtGui/QApplication>
            #include "buttonstack.h"
            
            int main(int argc, char** argv)
            {
            
                QApplication app (argc, argv);
                ButtonStack bs;
                bs.show();
                return app.exec();
            }
            
            C 1 Reply Last reply
            1
            • apalomerA apalomer

              Hello,
              I have found the solution. Now, instead of directly deleting the widget I use deleteLater() so the widget is scheduled to be destroyed when the control returns to the event loop. The final code can be found here and it looks like:

              Custom widget:

              #ifndef BUTTON_H
              #define BUTTON_H
              
              #include <QWidget>
              
              namespace Ui {
              class Button;
              }
              
              class Button : public QWidget
              {
                  Q_OBJECT
              
              public:
                  explicit Button(int n, QWidget *parent = 0);
                  ~Button();
              
              private slots:
                  void removeRequested();
              
              signals:
                  void remove(Button* button);
              private:
                  Ui::Button *ui;
              };
              
              #endif // BUTTON_H
              
              #include "button.h"
              #include "ui_button.h"
              
              Button::Button(int n, QWidget *parent) :
                  QWidget(parent),
                  ui(new Ui::Button)
              {
                  ui->setupUi(this);
                  ui->pushButton->setText("Remove button "+QString::number(n));
                  addAction(ui->actionRemove);
                  connect(ui->actionRemove,SIGNAL(triggered()),this,SLOT(removeRequested()));
                  connect(ui->pushButton,SIGNAL(clicked()),this,SLOT(removeRequested()));
              }
              
              Button::~Button()
              {
                  delete ui;
              }
              
              void Button::removeRequested()
              {
                  emit remove(this);
              }
              

              Main gui:

              #ifndef BUTTONSTACK_H
              #define BUTTONSTACK_H
              
              #include <QWidget>
              #include "button.h"
              
              namespace Ui {
              class ButtonStack;
              }
              
              class ButtonStack : public QWidget
              {
                  Q_OBJECT
              
              public:
                  explicit ButtonStack(QWidget *parent = 0);
                  ~ButtonStack();
              
              private slots:
                  void on_addButton_clicked();
                  void remove(Button* button);
              
              private:
                  Ui::ButtonStack *ui;
                  int total_buttons;
              };
              
              #endif // BUTTONSTACK_H
              
              #include "buttonstack.h"
              #include "ui_buttonstack.h"
              
              ButtonStack::ButtonStack(QWidget *parent) :
                  QWidget(parent),total_buttons(0),
                  ui(new Ui::ButtonStack)
              {
                  ui->setupUi(this);
              }
              
              ButtonStack::~ButtonStack()
              {
                  delete ui;
              }
              
              void ButtonStack::on_addButton_clicked()
              {
                  Button* button(new Button(total_buttons++));
                  ui->qvboxlayout->insertWidget(0,button);
                  connect(button,SIGNAL(remove(Button*)),this,SLOT(remove(Button*)));
              }
              
              void ButtonStack::remove(Button* button)
              {
                  ui->qvboxlayout->removeWidget(button);
                  button->deleteLater();
              }
              

              Main:

              #include <QtGui/QApplication>
              #include "buttonstack.h"
              
              int main(int argc, char** argv)
              {
              
                  QApplication app (argc, argv);
                  ButtonStack bs;
                  bs.show();
                  return app.exec();
              }
              
              C Offline
              C Offline
              Charlie_Hdz
              wrote on last edited by
              #6

              @apalomer Congratulations.

              Kind Regards,
              Enrique Hernandez
              gearstech.com.mx
              chernandez@gearstech.com.mx

              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