Evgenii Legotckoi
26 апреля 2018 г. 16:39

Qt/C++ - Урок 078. Не мешайте старый синтаксис сигналов на макросах SIGNAL SLOT и слотов с новым синтаксисом на указателях

Содержание

Все мы знаем, что в Qt существует два синтаксиса сигналов и слотов:

Но также, как не стоит мешать пиво с водкой, с таким же успехом не стоит смешивать два синтаксиса в рамках одного проекта.

Конечно, существуют проекты, в которых написано достаточно много кода и сделать полный рефакторинг по смене всего синтаксиса является довольно накладной работой, но если вы, постепенно дополняя проект, переходите на новый синтаксис, постарайтесь в рамках одного сигнала слотового соединения обновить все места кода с данным соединением на новый синтаксис.

Дело в том, что для обоих случаев ( SINGAL SLOT макросы и синтаксис на указателях ) формируется иное содержание moc файлов , что приводит к тому, что смешанное использование методов connect и disconnect не работает так, как ожидалось бы. А если быть точным, то метод disconnect не будет работать в том случае, если connect был вызван с использованием макросов, а disconnect был вызван с использованием указателей.


Пример

Создадим пробный проект, в котором будет окно и одна кнопка. Добавим в окне слот. И в конструкторе класса окна проверим четыре комбинации подключения сигнала кнопки к слоту окна:

  1. connect SIGNAL SLOT - disconnect SIGNAL SLOT
  2. connect SIGNAL SLOT - disconnect синтаксис на указателях
  3. connect на указателях - disconnect на указателях
  4. connect на указателях - disconnect SIGNAL SLOT

widget.h

  1. #ifndef WIDGET_H
  2. #define WIDGET_H
  3.  
  4. #include <QWidget>
  5.  
  6. namespace Ui {
  7. class Widget;
  8. }
  9.  
  10. class Widget : public QWidget
  11. {
  12. Q_OBJECT
  13.  
  14. public:
  15. explicit Widget(QWidget *parent = 0);
  16. ~Widget();
  17.  
  18. public slots:
  19. void checkSlot() {} // Slot for checking
  20.  
  21. private:
  22. Ui::Widget *ui;
  23. };
  24.  
  25. #endif // WIDGET_H

widget.cpp

  1. #include "widget.h"
  2. #include "ui_widget.h"
  3.  
  4. #include <QDebug>
  5.  
  6. Widget::Widget(QWidget *parent) :
  7. QWidget(parent),
  8. ui(new Ui::Widget)
  9. {
  10. ui->setupUi(this);
  11.  
  12. qDebug() << "First test";
  13. qDebug() << connect(ui->pushButton, SIGNAL(clicked(bool)), this, SLOT(checkSlot()));
  14. qDebug() << disconnect(ui->pushButton, SIGNAL(clicked(bool)), this, SLOT(checkSlot()));
  15.  
  16. qDebug() << "Second test";
  17. qDebug() << connect(ui->pushButton, SIGNAL(clicked(bool)), this, SLOT(checkSlot()));
  18. qDebug() << disconnect(ui->pushButton, &QPushButton::clicked, this, &Widget::checkSlot);
  19.  
  20. qDebug() << "Third test";
  21. qDebug() << connect(ui->pushButton,&QPushButton::clicked, this, &Widget::checkSlot);
  22. qDebug() << disconnect(ui->pushButton, &QPushButton::clicked, this, &Widget::checkSlot);
  23.  
  24. qDebug() << "Fourth test";
  25. qDebug() << connect(ui->pushButton,&QPushButton::clicked, this, &Widget::checkSlot);
  26. qDebug() << disconnect(ui->pushButton, SIGNAL(clicked(bool)), this, SLOT(checkSlot()));
  27. }
  28.  
  29. Widget::~Widget()
  30. {
  31. delete ui;
  32. }

Вывод

  1. First test
  2. true
  3. true
  4. Second test
  5. true
  6. false
  7. Third test
  8. true
  9. true
  10. Fourth test
  11. true
  12. true

Таким образом получается, что пара connect SINGAL SLOT - disconnect на указателях даёт не тот результат, который ожидался. И по факту слот остаётся подключённым.

Поэтому новичкам рекомендую внимательно относится к этому нюансу работы с сигналами и слотами в Qt.

Вам это нравится? Поделитесь в социальных сетях!

c
  • 3 мая 2018 г. 5:13

Who hasn’t mixed beer with vodka! 🤢🤮

Evgenii Legotckoi
  • 3 мая 2018 г. 13:38

vodka + beer = strong coctail, but it is bad ))

Юрий
  • 4 июня 2018 г. 22:41

disconnect - обязательно делать, во всех случаях?

Evgenii Legotckoi
  • 5 июня 2018 г. 2:03

Если удаляете объект, то все коннекты отключаются автоматически, здесь следить не требуется.

В остальных случаях disconnect нужно делать тогда, когда Вам нужно отключить сигнал-слотовое соединение в соответствии с логикой вашей программы, то есть на ваше усмотрение.

Комментарии

Только авторизованные пользователи могут публиковать комментарии.
Пожалуйста, авторизуйтесь или зарегистрируйтесь