ДК
Джон Кофи4. März 2020 08:14

Передача сигнала в функцию

Qt, signals

Привет. Можно ли передать в метод сигнал, как параметр и потом сделать коннект на него? код ниже конечно не работает.

_model->waitingFor(SIGNAL(Model::somesignal())); // no matching function for call to..

...
class Model : public QObject
{
    Q_OBJECT
public:
    explicit Model(QObject *parent = nullptr);

    void foo();
    void waitingFor(const char *signal); - не работает
//    void waitingFor(std::function<void()> &signal); - тоже не работает

signals:
    void somesignal();
};
...
void Model::waitingFor(const char *signal)
{
    QEventLoop evloop;
    connect(this, signal, &evloop, &QEventLoop::quit); // не соберется
    connect(this, SIGNAL(signal()), &evloop, SLOT(quit())); // соберется, но QObject::connect: No such signal Model::signal()
    evloop.exec();
}

*так тоже не работает

void Test::waitingFor2(std::function<QMetaMethod> &signal)
{
    QEventLoop evloop;
    connect(this, signal, &evloop, &QEventLoop::quit);
    evloop.exec();
}
Рекомендуємо хостинг TIMEWEB
Рекомендуємо хостинг TIMEWEB
Stabiles Hosting des sozialen Netzwerks EVILEG. Wir empfehlen VDS-Hosting für Django-Projekte.

Magst du es? In sozialen Netzwerken teilen!

6
Evgenii Legotckoi
  • 4. März 2020 08:51
  • (bearbeitet)
  • Die Antwort wurde als Lösung markiert.

Добрый день.

Можно передать сигнал, но лучше в виде указателей это всё делать, МАКРОСЫ следует изживать из проекта.

Также здесь следует использовать шаблоны. Конкретно ваш случай можно разрулить так

#ifndef MODEL_H
#define MODEL_H

#include <QEventLoop>

class Model : public QObject
{
    Q_OBJECT
public:
    explicit Model(QObject *parent = nullptr) : QObject(parent) {}

    template<typename TSignal>
    void waitingFor(TSignal&& signal)
    {
        QEventLoop evloop;
        connect(this, signal, &evloop, &QEventLoop::quit);
        evloop.exec();
    }

signals:
    void someSignal();
};

#endif // MODEL_H

И вызов метода

model->waitingFor(&Model::someSignal);

    великолепно. я уж начал сомневаться, что делаю решаемую задачу.

      Evgenii Legotckoi
      • 4. März 2020 09:10

      На макросах тоже можно, но лучше не надо. Кода больше получается, сам код в случае макросов требует применения SFINAE - в общем красивым код не назовёшь. Да и макросы менее надёжны.

        ДК
        • 4. März 2020 13:54
        • (bearbeitet)

        на работе просто собрал, а протестил вот сейчас дома- не отрабатывает коннект.

        class Test : public QObject
        {
            Q_OBJECT
        public:
            explicit Test(QObject *parent = nullptr) : QObject(parent) {}
        
            void foo()
            {
                qDebug() << "foo";
                emit somesignal();
            }
        
            template<typename TSignal>
            void waitingFor(TSignal &&signal)
            {
                qDebug() << "waitingFor";
                connect(this, signal, [](){ qDebug() << "signal received"; });
            }
        
        signals:
            void somesignal();
        };
        ...
        _test->foo();
        _test->waitingFor(&Test::somesignal);
        

        именно qDebug() << "signal received";
        Может нельзя передавать в метод сигнал, а потом соединяться с ним?

          ДК
          • 4. März 2020 14:20

          я вот думаю, что всё же правильней передавать const char *. Но всё равно тишина...

          class Test : public QObject
          {
              Q_OBJECT
          public:
              explicit Test(QObject *parent = nullptr) : QObject(parent) {}
          
              void foo()
              {
                  QTimer *timer = new QTimer;
                  timer->setSingleShot(true);
                  timer->start(5000);
                  connect(timer, &QTimer::timeout, timer, &QTimer::stop);
                  emit somesignal();
              }
          
              static void waitingFor(QObject *sender, const char *signalFromObj)
              {
                  qDebug() << "waitingFor";
                  QEventLoop loop;
                  connect(sender, signalFromObj, &loop, SLOT(quit()));
                  loop.exec();
              }
          
          signals:
              void somesignal();
          };
          ...
          _test->foo();
          Test::waitingFor(_test, SIGNAL(somesignal()));
          qDebug() << "mainwindow";
          

          qDebug() << "mainwindow"; не отработает.

            Evgenii Legotckoi
            • 4. März 2020 14:38
            • (bearbeitet)

            я вот думаю, что всё же правильней передавать const char *. Но всё равно тишина...

            Вы неправильно думаете. При компиляции проектов на C/C++ макросы разворачиваются в полноценный код, а в случае Qt присутствует ещё и этап создания moc файлов, в которых эти макросы уже интерпретируются в сигнатуры функций и создаётся код коннектов. И только потом уже происходит компиляция всех созданных исходников. В Qt не создаются налёту подключения сигналов и слотов из указателей на const char *, потому что SIGNAL и SLOT - это не строки, это макросы. Весь процесс создания кода в случае SIGNAL и SLOT для сигналов и слотов происходит на этапе ПРЕДКОМПИЛЯЦИИ, а не в рантайме. А то, что вы пытаетесь передавать указатель на const char - это рантайм.

            Я вам дал полностью рабочий пример кода, который оттестировал и запустил.

            Вот модифицированный вариант, который тоже работает.

            #ifndef MODEL_H
            #define MODEL_H
            
            #include <QEventLoop>
            #include <QDebug>
            
            class Model : public QObject
            {
                Q_OBJECT
            public:
                explicit Model(QObject *parent = nullptr) : QObject(parent) {}
            
                template<typename TSignal>
                void waitingFor(TSignal&& signal)
                {
                    connect(this, signal, [](){ qDebug() << "Signal emitted"; });
                }
            
            signals:
                void someSignal();
            };
            
            #endif // MODEL_H
            
            

            Вот так его можно использовать

            widget.h

            #ifndef WIDGET_H
            #define WIDGET_H
            
            #include <QWidget>
            #include "model.h"
            
            QT_BEGIN_NAMESPACE
            namespace Ui { class Widget; }
            QT_END_NAMESPACE
            
            class Widget : public QWidget
            {
                Q_OBJECT
            
            public:
                Widget(QWidget *parent = nullptr);
                ~Widget();
            
            private slots:
                void on_pushButton_clicked();
            
                void on_sendSignalButton_clicked();
            
            private:
                Ui::Widget *ui;
            
                Model m_model;
            };
            #endif // WIDGET_H
            
            

            widget.cpp

            #include "widget.h"
            #include "ui_widget.h"
            
            Widget::Widget(QWidget *parent)
                : QWidget(parent)
                , ui(new Ui::Widget)
            {
                ui->setupUi(this);
            }
            
            Widget::~Widget()
            {
                delete ui;
            }
            
            void Widget::on_pushButton_clicked()
            {
                m_model.waitingFor(&Model::someSignal);
            }
            
            void Widget::on_sendSignalButton_clicked()
            {
                emit m_model.someSignal();
            }
            
            

            Вот тестовый проект

            CheckSignals.zip CheckSignals.zip

              Kommentare

              Nur autorisierte Benutzer können Kommentare posten.
              Bitte Anmelden oder Registrieren
              Letzte Kommentare
              A
              ALO1ZE19. Oktober 2024 08:19
              Fb3-Dateileser auf Qt Creator Подскажите как это запустить? Я не шарю в программировании и кодинге. Скачал и установаил Qt, но куча ошибок выдается и не запустить. А очень надо fb3 переконвертировать в html
              ИМ
              Игорь Максимов5. Oktober 2024 07:51
              Django – Lektion 064. So schreiben Sie eine Python-Markdown-Erweiterung Приветствую Евгений! У меня вопрос. Можно ли вставлять свои классы в разметку редактора markdown? Допустим имея стандартную разметку: <ul> <li></li> <li></l…
              d
              dblas55. Juli 2024 11:02
              QML - Lektion 016. SQLite-Datenbank und das Arbeiten damit in QML Qt Здравствуйте, возникает такая проблема (я новичок): ApplicationWindow неизвестный элемент. (М300) для TextField и Button аналогично. Могу предположить, что из-за более новой верси…
              k
              kmssr8. Februar 2024 18:43
              Qt Linux - Lektion 001. Autorun Qt-Anwendung unter Linux как сделать автозапуск для флэтпака, который не даёт создавать файлы в ~/.config - вот это вопрос ))
              Qt WinAPI - Lektion 007. Arbeiten mit ICMP-Ping in Qt Без строки #include <QRegularExpressionValidator> в заголовочном файле не работает валидатор.
              Jetzt im Forum diskutieren
              J
              JacobFib17. Oktober 2024 03:27
              добавить qlineseries в функции Пользователь может получить любые разъяснения по интересующим вопросам, касающимся обработки его персональных данных, обратившись к Оператору с помощью электронной почты https://topdecorpro.ru…
              JW
              Jhon Wick1. Oktober 2024 15:52
              Indian Food Restaurant In Columbus OH| Layla’s Kitchen Indian Restaurant If you're looking for a truly authentic https://www.laylaskitchenrestaurantohio.com/ , Layla’s Kitchen Indian Restaurant is your go-to destination. Located at 6152 Cleveland Ave, Colu…
              КГ
              Кирилл Гусарев27. September 2024 09:09
              Не запускается программа на Qt: точка входа в процедуру не найдена в библиотеке DLL Написал программу на C++ Qt в Qt Creator, сбилдил Release с помощью MinGW 64-bit, бинарнику напихал dll-ки с помощью windeployqt.exe. При попытке запуска моей сбилженной программы выдаёт три оши…
              F
              Fynjy22. Juli 2024 04:15
              при создании qml проекта Kits есть но недоступны для выбора Поставил Qt Creator 11.0.2. Qt 6.4.3 При создании проекта Qml не могу выбрать Kits, они все недоступны, хотя настроены и при создании обычного Qt Widget приложения их можно выбрать. В чем может …

              Folgen Sie uns in sozialen Netzwerken