Alexander
Alexander7. März 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
Stabiles Hosting des sozialen Netzwerks EVILEG. Wir empfehlen VDS-Hosting für Django-Projekte.

Magst du es? In sozialen Netzwerken teilen!

28
Docent
  • 7. März 2020 14:32
  • Die Antwort wurde als Lösung markiert.

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

    Alexander
    • 7. März 2020 14:56

    Спасибо

      Алексей Внуков
      • 7. März 2020 17:32

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

        Alexander
        • 8. März 2020 12:58

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

          Evgenii Legotckoi
          • 8. März 2020 13:23

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

            Alexander
            • 9. März 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
              • 9. März 2020 15:52

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

                Evgenii Legotckoi
                • 9. März 2020 15:54
                • (bearbeitet)

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

                  Alexander
                  • 9. März 2020 17:53

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

                    Evgenii Legotckoi
                    • 9. März 2020 18:14
                    • (bearbeitet)

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

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

                        Alexander
                        • 9. März 2020 18:42

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

                          Alexander
                          • 9. März 2020 19:00

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

                            Evgenii Legotckoi
                            • 9. März 2020 19:07

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

                              Alexander
                              • 9. März 2020 19:20

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

                                Alexander
                                • 11. März 2020 06:09

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

                                connect(SClients[idUserSocs],&QTcpSocket::disconnected,this,&SWCore::slotDisClient(socketDescriptor);
                                
                                  Alexander
                                  • 11. März 2020 06:11

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

                                    Evgenii Legotckoi
                                    • 11. März 2020 06:50
                                    • (bearbeitet)

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

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

                                    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. März 2020 07:25

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

                                        Alexander
                                        • 11. März 2020 07:27

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

                                          Evgenii Legotckoi
                                          • 11. März 2020 07:29

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

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

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

                                              Evgenii Legotckoi
                                              • 11. März 2020 07:47

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

                                                Alexander
                                                • 11. März 2020 09:56

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

                                                  Alexander
                                                  • 11. März 2020 14:30

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

                                                    Alexander
                                                    • 11. März 2020 14:30

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

                                                      Evgenii Legotckoi
                                                      • 12. März 2020 04:18
                                                      • (bearbeitet)

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

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

                                                        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