Alexander
AlexanderНаурыз 7, 2020, 1: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
  • Наурыз 7, 2020, 2:32 Т.Қ.
  • Жауап шешім ретінде белгіленді.

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

    Alexander
    • Наурыз 7, 2020, 2:56 Т.Қ.

    Спасибо

      Алексей Внуков
      • Наурыз 7, 2020, 5:32 Т.Қ.

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

        Alexander
        • Наурыз 8, 2020, 12:58 Т.Қ.

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

          Evgenii Legotckoi
          • Наурыз 8, 2020, 1:23 Т.Қ.

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

            Alexander
            • Наурыз 9, 2020, 3: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, 2020, 3:52 Т.Қ.

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

                Evgenii Legotckoi
                • Наурыз 9, 2020, 3:54 Т.Қ.
                • (өңделген)

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

                  Alexander
                  • Наурыз 9, 2020, 5:53 Т.Қ.

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

                    Evgenii Legotckoi
                    • Наурыз 9, 2020, 6: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
                      • Наурыз 9, 2020, 6:34 Т.Қ.

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

                        Alexander
                        • Наурыз 9, 2020, 6:42 Т.Қ.

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

                          Alexander
                          • Наурыз 9, 2020, 7 Т.Қ.

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

                            Evgenii Legotckoi
                            • Наурыз 9, 2020, 7:07 Т.Қ.

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

                              Alexander
                              • Наурыз 9, 2020, 7:20 Т.Қ.

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

                                Alexander
                                • Наурыз 11, 2020, 6:09 Т.Ж.

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

                                connect(SClients[idUserSocs],&QTcpSocket::disconnected,this,&SWCore::slotDisClient(socketDescriptor);
                                
                                  Alexander
                                  • Наурыз 11, 2020, 6:11 Т.Ж.

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

                                    Evgenii Legotckoi
                                    • Наурыз 11, 2020, 6: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, 7:25 Т.Ж.

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

                                        Alexander
                                        • Наурыз 11, 2020, 7:27 Т.Ж.

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

                                          Evgenii Legotckoi
                                          • Наурыз 11, 2020, 7:29 Т.Ж.

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

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

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

                                              Evgenii Legotckoi
                                              • Наурыз 11, 2020, 7:47 Т.Ж.

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

                                                Alexander
                                                • Наурыз 11, 2020, 9:56 Т.Ж.

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

                                                  Alexander
                                                  • Наурыз 11, 2020, 2:30 Т.Қ.

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

                                                    Alexander
                                                    • Наурыз 11, 2020, 2:30 Т.Қ.

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

                                                      Evgenii Legotckoi
                                                      • Наурыз 12, 2020, 4:18 Т.Ж.
                                                      • (өңделген)

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

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

                                                        Пікірлер

                                                        Тек рұқсаты бар пайдаланушылар ғана пікір қалдыра алады.
                                                        Кіріңіз немесе Тіркеліңіз
                                                        Г

                                                        C++ - Тест 001. Первая программа и типы данных

                                                        • Нәтиже:66ұпай,
                                                        • Бағалау ұпайлары-1
                                                        t

                                                        C++ - Тест 001. Первая программа и типы данных

                                                        • Нәтиже:33ұпай,
                                                        • Бағалау ұпайлары-10
                                                        t

                                                        Qt - Тест 001. Сигналы и слоты

                                                        • Нәтиже:52ұпай,
                                                        • Бағалау ұпайлары-4
                                                        Соңғы пікірлер
                                                        G
                                                        GoattRockҚыр. 3, 2024, 1:50 Т.Қ.
                                                        Linux жүйесінде файлдарды қалай көшіруге болады Задумывались когда-нибудь о том, как мы привыкли доверять свои вещи службам грузоперевозок? Сейчас такие услуги стали неотъемлемой частью нашей жизни, особенно когда речь идет о переездах между …
                                                        d
                                                        dblas5Шілде 5, 2024, 11:02 Т.Ж.
                                                        QML - Сабақ 016. SQLite деректер қоры және онымен QML Qt-та жұмыс істеу Здравствуйте, возникает такая проблема (я новичок): ApplicationWindow неизвестный элемент. (М300) для TextField и Button аналогично. Могу предположить, что из-за более новой верси…
                                                        k
                                                        kmssrАқп. 8, 2024, 6:43 Т.Қ.
                                                        Qt Linux - Сабақ 001. Linux астында Autorun Qt қолданбасы как сделать автозапуск для флэтпака, который не даёт создавать файлы в ~/.config - вот это вопрос ))
                                                        АК
                                                        Анатолий КононенкоАқп. 5, 2024, 1:50 Т.Ж.
                                                        Qt WinAPI - Сабақ 007. Qt ішінде ICMP Ping арқылы жұмыс істеу Без строки #include <QRegularExpressionValidator> в заголовочном файле не работает валидатор.
                                                        Енді форумда талқылаңыз
                                                        Evgenii Legotckoi
                                                        Evgenii LegotckoiМаусым 24, 2024, 3:11 Т.Қ.
                                                        добавить qlineseries в функции Я тут. Работы оень много. Отправил его в бан.
                                                        F
                                                        FynjyШілде 22, 2024, 4:15 Т.Ж.
                                                        при создании qml проекта Kits есть но недоступны для выбора Поставил Qt Creator 11.0.2. Qt 6.4.3 При создании проекта Qml не могу выбрать Kits, они все недоступны, хотя настроены и при создании обычного Qt Widget приложения их можно выбрать. В чем может …
                                                        BlinCT
                                                        BlinCTМаусым 25, 2024, 1 Т.Ж.
                                                        Нарисовать кривую в qml Всем привет. Имеется Лист листов с тосками, точки получаны интерполяцией Лагранжа. Вопрос, как этими точками нарисовать кривую? ChartView отпадает сразу, в qt6.7 появился новый элемент…
                                                        BlinCT
                                                        BlinCTМамыр 5, 2024, 5:46 Т.Ж.
                                                        Написать свой GraphsView Всем привет. В Qt есть давольно старый обьект дял работы с графиками ChartsView и есть в 6.7 новый но очень сырой и со слабым функционалом GraphsView. По этой причине я хочу написать х…
                                                        Evgenii Legotckoi
                                                        Evgenii LegotckoiМамыр 2, 2024, 2:07 Т.Қ.
                                                        Мобильное приложение на C++Qt и бэкенд к нему на Django Rest Framework Добрый день. По моему мнению - да, но то, что будет касаться вызовов к функционалу Андроида, может создать огромные трудности.

                                                        Бізді әлеуметтік желілерде бақылаңыз