Alexander
Alexander07 березня 2020 р. 13:23

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

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

Вопрос такого плана. Допустим есть Класс логики "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);
}

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

Рекомендуємо хостинг TIMEWEB
Рекомендуємо хостинг TIMEWEB
Стабільний хостинг, на якому розміщується соціальна мережа EVILEG. Для проектів на Django радимо VDS хостинг.

Вам це подобається? Поділіться в соціальних мережах!

28
Docent
  • 07 березня 2020 р. 14:32
  • Відповідь була позначена як рішення.

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

    Alexander
    • 07 березня 2020 р. 14:56

    Спасибо

      Алексей Внуков
      • 07 березня 2020 р. 17:32

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

        Alexander
        • 08 березня 2020 р. 12:58

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

          Evgenii Legotckoi
          • 08 березня 2020 р. 13:23

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

            Alexander
            • 09 березня 2020 р. 15:26

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

                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
              • 09 березня 2020 р. 15:52

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

                Evgenii Legotckoi
                • 09 березня 2020 р. 15:54
                • (відредаговано)

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

                  Alexander
                  • 09 березня 2020 р. 17:53

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

                    Evgenii Legotckoi
                    • 09 березня 2020 р. 18:14
                    • (відредаговано)

                    Нет, не совсем. Сигнал-слотовые соединения могут запускать потоко-безопасно методы объектов, которые находятся в других потоках. Но если сигнал и слот находятся в одном потоке, то вызов сигнала запускает выполнение всех слотов, которые привязаны к сигналу, и пока не выполнятся все слоты, то выполнение программы дальше места вызова сигнала не пойдёт. При этом в 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
                      • 09 березня 2020 р. 18:34

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

                        Alexander
                        • 09 березня 2020 р. 18:42

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

                          Alexander
                          • 09 березня 2020 р. 19:00

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

                            Evgenii Legotckoi
                            • 09 березня 2020 р. 19:07

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

                              Alexander
                              • 09 березня 2020 р. 19:20

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

                                Alexander
                                • 11 березня 2020 р. 06:09

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

                                connect(SClients[idUserSocs],&QTcpSocket::disconnected,this,&SWCore::slotDisClient(socketDescriptor);
                                
                                  Alexander
                                  • 11 березня 2020 р. 06:11

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

                                    Evgenii Legotckoi
                                    • 11 березня 2020 р. 06:50
                                    • (відредаговано)

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

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

                                    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
                                      • 11 березня 2020 р. 07:25

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

                                        Alexander
                                        • 11 березня 2020 р. 07:27

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

                                          Evgenii Legotckoi
                                          • 11 березня 2020 р. 07:29

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

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

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

                                              Evgenii Legotckoi
                                              • 11 березня 2020 р. 07:47

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

                                                Alexander
                                                • 11 березня 2020 р. 09:56

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

                                                  Alexander
                                                  • 11 березня 2020 р. 14:30

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

                                                    Alexander
                                                    • 11 березня 2020 р. 14:30

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

                                                      Evgenii Legotckoi
                                                      • 12 березня 2020 р. 04:18
                                                      • (відредаговано)

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

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

                                                        Коментарі

                                                        Only authorized users can post comments.
                                                        Please, Log in or Sign up
                                                        AD

                                                        C++ - Тест 004. Указатели, Массивы и Циклы

                                                        • Результат:50бали,
                                                        • Рейтинг балів-4
                                                        m
                                                        • molni99
                                                        • 26 жовтня 2024 р. 01:37

                                                        C++ - Тест 004. Указатели, Массивы и Циклы

                                                        • Результат:80бали,
                                                        • Рейтинг балів4
                                                        m
                                                        • molni99
                                                        • 26 жовтня 2024 р. 01:29

                                                        C++ - Тест 004. Указатели, Массивы и Циклы

                                                        • Результат:20бали,
                                                        • Рейтинг балів-10
                                                        Останні коментарі
                                                        ИМ
                                                        Игорь Максимов22 листопада 2024 р. 11:51
                                                        Django - Підручник 017. Налаштуйте сторінку входу до Django Добрый вечер Евгений! Я сделал себе авторизацию аналогичную вашей, все работает, кроме возврата к предидущей странице. Редеректит всегда на главную, хотя в логах сервера вижу запросы на правильн…
                                                        Evgenii Legotckoi
                                                        Evgenii Legotckoi31 жовтня 2024 р. 14:37
                                                        Django - Урок 064. Як написати розширення для Python Markdown Добрый день. Да, можно. Либо через такие же плагины, либо с постобработкой через python библиотеку Beautiful Soup
                                                        A
                                                        ALO1ZE19 жовтня 2024 р. 08:19
                                                        Читалка файлів fb3 на Qt Creator Подскажите как это запустить? Я не шарю в программировании и кодинге. Скачал и установаил Qt, но куча ошибок выдается и не запустить. А очень надо fb3 переконвертировать в html
                                                        ИМ
                                                        Игорь Максимов05 жовтня 2024 р. 07:51
                                                        Django - Урок 064. Як написати розширення для Python Markdown Приветствую Евгений! У меня вопрос. Можно ли вставлять свои классы в разметку редактора markdown? Допустим имея стандартную разметку: <ul> <li></li> <li></l…
                                                        d
                                                        dblas505 липня 2024 р. 11:02
                                                        QML - Урок 016. База даних SQLite та робота з нею в QML Qt Здравствуйте, возникает такая проблема (я новичок): ApplicationWindow неизвестный элемент. (М300) для TextField и Button аналогично. Могу предположить, что из-за более новой верси…
                                                        Тепер обговоріть на форумі
                                                        Evgenii Legotckoi
                                                        Evgenii Legotckoi24 червня 2024 р. 15:11
                                                        добавить qlineseries в функции Я тут. Работы оень много. Отправил его в бан.
                                                        t
                                                        tonypeachey115 листопада 2024 р. 06:04
                                                        google domain [url=https://google.com/]domain[/url] domain [http://www.example.com link title]
                                                        NSProject
                                                        NSProject04 червня 2022 р. 03:49
                                                        Всё ещё разбираюсь с кешем. В следствии прочтения данной статьи. Я принял для себя решение сделать кеширование свойств менеджера модели LikeDislike. И так как установка evileg_core для меня не была возможна, ибо он писался…
                                                        9
                                                        9Anonim25 жовтня 2024 р. 09:10
                                                        Машина тьюринга // Начальное состояние 0 0, ,<,1 // Переход в состояние 1 при пустом символе 0,0,>,0 // Остаемся в состоянии 0, двигаясь вправо при встрече 0 0,1,>…

                                                        Слідкуйте за нами в соціальних мережах