Alexander
AlexanderMarch 7, 2020, 1:23 p.m.

Организация передачи данных из сигнала в слот

Доброго времени суток.

Вопрос такого плана. Допустим есть Класс логики "SWCore" и класс GUI "GUICore"
В логике во время какого то действия "происходит" сообщения ("new connections") или на подобие, в целях пример важно что данные QString. Дальше на форме GUICore есть элемент типа QTextEdit. У него есть метод append (который добавляет текст на виджет) Так вот как бы мне написать конеект с передачей этих самых данных. Код для наглядности:


struct Clients{
    int idClient;
    QTcpSocket *TcpSocket;
    QString nameClient;
};

class SoftWareCore : public QObject
{
    Q_OBJECT
public:
    SoftWareCore();
    QVector<Clients> getClientsList() const;
    void setClientsList(const QVector<Clients> &value);

public slots:
    void slotNewConnection();
    void slotServerRead();
    void slotClientDisconnected();
signals:
    void newMsgServ(QString msg);
private:
    Clients cl;
    QVector <Clients> clientsList;
    int countClients;
    QTcpServer * mTcpServer;
    QTcpSocket * mTcpSocket;
};
class GUICore : public QMainWindow
{
    Q_OBJECT
public:
    GUICore(QWidget *parent = nullptr);
    ~GUICore();
private slots:
    void addToPlaneText(QString msg);
private:
    Ui::GUICore *ui;
    SoftWareCore *SWC;
};
void GUICore::addToPlaneText(QString msg)
{
    ui->textEdit->append(msg);
}

вот прям совсем не доганю как должен выглядить коннект

We recommend hosting TIMEWEB
We recommend hosting TIMEWEB
Stable hosting, on which the social network EVILEG is located. For projects on Django we recommend VDS hosting.

Do you like it? Share on social networks!

28
Docent
  • March 7, 2020, 2:32 p.m.
  • The answer was marked as a solution.

создаете signal mysign(QString);
В нужное время emit mysign("text");
Ну и коннект connect(class1, SIGNAL(mysign(QString)), class2.textEdit, SLOT(append(QStting)));

    Alexander
    • March 7, 2020, 2:56 p.m.

    Спасибо

      Алексей Внуков
      • March 7, 2020, 5:32 p.m.

      так же конекты отлично поддерживают лямбда-функции, так же хочу обрать внимание на то что коннект типа connect(class1, SIGNAL(mysign(QString)), class2.textEdit, SLOT(append(QStting))) - это старый стиль, и Qt рекомендует использовать только новый стиль
      connect(class1, &Class1::signal, class2,&Class2::func_slot);

        Alexander
        • March 8, 2020, 12:58 p.m.

        А такой вопрос не черевато что в коннектох использую this без явного указания?

          Evgenii Legotckoi
          • March 8, 2020, 1:23 p.m.

          Что вы понимаете под явным указанием? this указывает в классе сам на себя, то есть на объект класса внутри себя, это тоже самое, что указывать имя объекта в сигнал слотовое соединение (грубо говоря, поскольку this эквивалентно указателю), так что разницы нет.

            Alexander
            • March 9, 2020, 3:26 p.m.

            Я понимаю под явным указанием такую запись

                connect (swc,   &SWCore::alive,           this,   &GUICore::isAlive);
                connect (swc,   &SWCore::newMsgServ,      this,   &GUICore::addToPlaneText);
                connect (swc,   &SWCore::newClient,       this,   &GUICore::newConnectionClient);
                connect (swc,   &SWCore::disconectClients,this,   &GUICore::deleteConnectionClient);
            

            тоесть в данном примере swc, но так эти конекты пишутся в конструкторе GUICore то явно уцказать его не получается, только this. Так как помню с js указатель this является не безопасным, вот и интересуюсь не является ли он (this) тоже не совсем безопасным в cpp

              Evgenii Legotckoi
              • March 9, 2020, 3:52 p.m.

              В случае с this предполагается, что объект существует, по крайней мере на момент передачи указателя this во время выполнения кода.
              Но естественно, если передать объект через this в какую-нибудь функцию или метод другого объекта, а потом в ходе выполнения кода объект, указатель this которого передавался в другой объект, будет удалён, но при этом указатель останется во втором объекте, то в ходе выполнения алгоритма программы можно получить падение программы. То есть указатель this , как впрочем и указатель объекта swc одинаково небезопасны, они равноценно небезопасны. Но в случае с connect методом всё гораздо проще, при уничтожении объектов сигнал-слотовое соединение разрушается автоматически, это обеспечивается архитектурой Qt фреймворка. Так что тут проблем нет.

                Evgenii Legotckoi
                • March 9, 2020, 3:54 p.m.
                • (edited)

                Если коротко, то в C++ this - это указатель объекта на самого себя внутри класса, работает абсолютно так же, как и любой другой указатель на объект, например swc в вашем примере. Так что их уровень безопасноти одинаков.

                  Alexander
                  • March 9, 2020, 5:53 p.m.

                  Большое спасибо за обширный ответ. И последний ворос, я же правельно понимаю что система сигнал-слот является асинхронным и не блокирует выполнения процесса до завершения процесса который запушен сигналом?

                    Evgenii Legotckoi
                    • March 9, 2020, 6:14 p.m.
                    • (edited)

                    Нет, не совсем. Сигнал-слотовые соединения могут запускать потоко-безопасно методы объектов, которые находятся в других потоках. Но если сигнал и слот находятся в одном потоке, то вызов сигнала запускает выполнение всех слотов, которые привязаны к сигналу, и пока не выполнятся все слоты, то выполнение программы дальше места вызова сигнала не пойдёт. При этом в Qt присутствует очередь вызовов слотов, это было сделано для реализации многопоточности. Таким образом все вызовы слотов с разных потоков ставятся в очередь и выполняются поочерёдно. Поэтому они и считаются потокобезопасными, хотя конечно мьютексы стоит использовать в слотах, иначе можно угробить данные.

                    Что касается блокировки, то выглядит это так, допустим имеется несколько сигналов и слотов и мы знаем условное среднее время выполнение слота на абстрактном ПК.

                    signals:
                        void signal_1();
                        void signal_2();
                        void signal_3();
                    
                    public slots:
                        void slot_1(); // 1 секунда выполнения
                        void slot_2(); // 500 мс
                        void slot_3(); // 200 мс
                    

                    Допустим, мы где-то сделали подключения этих сигналов и слотов (неважно, где и как делали коннекты).
                    И начинаем их вызывать. Если объекты не находятся в разных потоков, а весь код у нас вертится в GUI-потоке, то есть в главном потоке, то получаем следующую ситуацию.

                    emit signal_2(); // вызывается где-то slot_2() - 500 мс
                    emit signal_1(); // вызывается где-то slot_1() - 1 секунда выполнения
                    emit signal_2(); // вызывается где-то slot_2() - 500 мс
                    emit signal_3(); // вызывается где-то slot_3() - 200 мс
                    

                    Как результат, GUI морозится на 2200 мс,

                    Но если какую-то логику переводить в рабочие потоки, то конечно можно избежать заморозки GUI. Это уже вопрос архитектуры. Так что с помощью сигналов и слотов можно добиться асинхронности, но только, если разбивать выполнение кода на потоки, а не крутить всё внутри главного GUI потока.

                      Alexander
                      • March 9, 2020, 6:34 p.m.

                      Мда теперь надо выводить мою логику в другой поток что бы не гасить гуй. спасибо еще раз пошел гуглить.

                        Alexander
                        • March 9, 2020, 6:42 p.m.

                        Ах какая красота. Сейчас почитаем

                          Alexander
                          • March 9, 2020, 7 p.m.

                          да ладно, все так просто? я пол года бегал во круг поток, не мог понять. Большое тебе спасибо мил человек. Тут по любому нужен донат!!!

                            Evgenii Legotckoi
                            • March 9, 2020, 7:07 p.m.

                            Ну нюансов много в процессе работы с потоками всплывает, тоже самое использование мьютексов. Помимо QThread есть ещё QThreadPool, QtConcurrent, достаточно своих нюансов, а также всё для своей области применения.

                              Alexander
                              • March 9, 2020, 7:20 p.m.

                              Ну пока длч моих целей достаточно тех 3х ссылок. Я не много переделываю Ваш EchoServer на несколько клиентов и с вещянием сигнала и последующим построением графика на клиенском приложении, так сказать тестовое задание себе в портфолио хочу сделать. )

                                Alexander
                                • March 11, 2020, 6:09 a.m.

                                А можно ли конектить сигналы со слотами котрые отличаются по сигнатуре? например

                                connect(SClients[idUserSocs],&QTcpSocket::disconnected,this,&SWCore::slotDisClient(socketDescriptor);
                                
                                  Alexander
                                  • March 11, 2020, 6:11 a.m.

                                  или можно ли как то получить указатель на отправителя сигнала, тоесть класс получает в слот сигнал, можно ли понять кто его отправил?

                                    Evgenii Legotckoi
                                    • March 11, 2020, 6:50 a.m.
                                    • (edited)

                                    Лучше покажите сигнатуру отдельно, как объявлено в заголовочном файле.

                                    Но по сути правило такое: сигнатура слота должна полностью совпадать с сигнатурой сигнала или первой частью сигнатуры сигнала, то есть возможны такие варианты

                                    void signal() -> void slot()
                                    void signal(QString) -> void slot(QString)
                                    void signal(QString, QString) -> void slot(QString)
                                    

                                    Такие варианты невозможны

                                    void signal() -> void slot(QString)
                                    void signal(QString) -> void slot(double)
                                    void signal(QString, QString) -> void slot(QString, QString)
                                    

                                    Возможно подключение сигнала к сигналу, правило такое же, как подключение сигнала к слоту

                                    void signal_1() -> void signal_2()
                                    void signal_1(QString) -> void signal_2(QString)
                                    void signal_1(QString, QString) -> void slot_2(QString)
                                    

                                    Варианты с подключением, когда сигнатуры отличаются, можно вырешить через лямбда функции

                                    connect(SClients[idUserSocs], &QTcpSocket::disconnected, this, [this](){ slotDisClient(); });
                                    
                                      Alexander
                                      • March 11, 2020, 7:25 a.m.

                                      Просто я к чему это, что бы не переопределять сигнал &QTcpSocket::disconnected(), который без агрументов, мне надо понимать какой дискриптер его пораждает, что бы правельно удалить ссылку на него в масиве логики и списке клиентов в гуи

                                        Alexander
                                        • March 11, 2020, 7:27 a.m.

                                        А с лямбдой идея, сейчас попробую

                                          Evgenii Legotckoi
                                          • March 11, 2020, 7:29 a.m.

                                          Все классы, которые наследованы от QObject имеют метод sender(), который возвращает указатель на отправителя сигнала. Так что вам просто нужно написать слот с проверкой отправителя.

                                          void SWCore::slotDisClient()
                                          {
                                              QObject* s = sender();
                                          
                                              // Далее сравнить указатель с вектором указателей на объекты, которые могли бы выслать этот сигнал.
                                          }
                                          
                                            Alexander
                                            • March 11, 2020, 7:37 a.m.

                                            О мерси, кстати по донату нет вариантов на карту а то яндекс деньги нема?

                                              Evgenii Legotckoi
                                              • March 11, 2020, 7:47 a.m.

                                              на яндекс деньги можно и с карты переслать

                                                Alexander
                                                • March 11, 2020, 9:56 a.m.

                                                не когда не пробывал, с утра затесьтю

                                                  Alexander
                                                  • March 11, 2020, 2:30 p.m.

                                                  А в продолжения темы про потоки, а совсем плохо если дочерний процес запустить еще процессы в колличестве 5-6 штук?

                                                    Alexander
                                                    • March 11, 2020, 2:30 p.m.

                                                    А в продолжения темы про потоки, а совсем плохо если дочерний процес запустить еще процессы в колличестве 5-6 штук?

                                                      Evgenii Legotckoi
                                                      • March 12, 2020, 4:18 a.m.
                                                      • (edited)

                                                      Да для потоков-то это не принципиально, вопрос в том, как это будет разруливаться, чтобы утечек памяти не было. И от итоговой архитектуры будет зависеть. Если архитектура приложения будет паршивой, трудночитаемой и трудноподдерживаемой, то ничего хорошего не выйдет, а так, лично я не вижу у этом проблем, хотя и не представляю кейсов, где бы это действительно нужно было.

                                                      P/S/ вы не могли бы структурировать вопросы и создавать на них новые темы на форуме, иначе тема уже превращается в сборник оффтопов и лучше будет, чтобы был вопрос и его решение, а не вольное обсуждение всего и вся. Даже это обсуждение уже можно было бы разбить, наверное, на три отдельных вопроса. Как никак это форум, а не чат.

                                                        Comments

                                                        Only authorized users can post comments.
                                                        Please, Log in or Sign up
                                                        г
                                                        • ги
                                                        • April 23, 2024, 3:51 p.m.

                                                        C++ - Test 005. Structures and Classes

                                                        • Result:41points,
                                                        • Rating points-8
                                                        l
                                                        • laei
                                                        • April 23, 2024, 9:19 a.m.

                                                        C ++ - Test 004. Pointers, Arrays and Loops

                                                        • Result:10points,
                                                        • Rating points-10
                                                        l
                                                        • laei
                                                        • April 23, 2024, 9:17 a.m.

                                                        C++ - Тест 003. Условия и циклы

                                                        • Result:50points,
                                                        • Rating points-4
                                                        Last comments
                                                        k
                                                        kmssrFeb. 8, 2024, 6:43 p.m.
                                                        Qt Linux - Lesson 001. Autorun Qt application under Linux как сделать автозапуск для флэтпака, который не даёт создавать файлы в ~/.config - вот это вопрос ))
                                                        Qt WinAPI - Lesson 007. Working with ICMP Ping in Qt Без строки #include <QRegularExpressionValidator> в заголовочном файле не работает валидатор.
                                                        EVA
                                                        EVADec. 25, 2023, 10:30 a.m.
                                                        Boost - static linking in CMake project under Windows Ошибка LNK1104 часто возникает, когда компоновщик не может найти или открыть файл библиотеки. В вашем случае, это файл libboost_locale-vc142-mt-gd-x64-1_74.lib из библиотеки Boost для C+…
                                                        J
                                                        JonnyJoDec. 25, 2023, 8:38 a.m.
                                                        Boost - static linking in CMake project under Windows Сделал всё по-как у вас, но выдаёт ошибку [build] LINK : fatal error LNK1104: не удается открыть файл "libboost_locale-vc142-mt-gd-x64-1_74.lib" Хоть убей, не могу понять в чём дел…
                                                        G
                                                        GvozdikDec. 18, 2023, 9:01 p.m.
                                                        Qt/C++ - Lesson 056. Connecting the Boost library in Qt for MinGW and MSVC compilers Для решения твой проблемы добавь в файл .pro строчку "LIBS += -lws2_32" она решит проблему , лично мне помогло.
                                                        Now discuss on the forum
                                                        G
                                                        GarApril 22, 2024, 5:46 a.m.
                                                        Clipboard Как скопировать окно целиком в clipb?
                                                        DA
                                                        Dr Gangil AcademicsApril 20, 2024, 7:45 a.m.
                                                        Unlock Your Aesthetic Potential: Explore MSC in Facial Aesthetics and Cosmetology in India Embark on a transformative journey with an msc in facial aesthetics and cosmetology in india . Delve into the intricate world of beauty and rejuvenation, guided by expert faculty and …
                                                        a
                                                        a_vlasovApril 14, 2024, 6:41 a.m.
                                                        Мобильное приложение на C++Qt и бэкенд к нему на Django Rest Framework Евгений, добрый день! Такой вопрос. Верно ли следующее утверждение: Любое Android-приложение, написанное на Java/Kotlin чисто теоретически (пусть и с большими трудностями) можно написать и на C+…
                                                        Павел Дорофеев
                                                        Павел ДорофеевApril 14, 2024, 2:35 a.m.
                                                        QTableWidget с 2 заголовками Вот тут есть кастомный QTableView с многорядностью проект поддерживается, обращайтесь
                                                        f
                                                        fastrexApril 4, 2024, 4:47 a.m.
                                                        Вернуть старое поведение QComboBox, не менять индекс при resetModel Добрый день! У нас много проектов в которых используется QComboBox, в версии 5.5.1, когда модель испускает сигнал resetModel, currentIndex не менялся. В версии 5.15 при resetModel происходит try…

                                                        Follow us in social networks