Временно деактивировать соединение Qt C ++ - PullRequest
0 голосов
/ 20 января 2020

Я пытаюсь временно удалить это соединение:

connect(clipBoard, SIGNAL(dataChanged()), this, SLOT(copiage()));  (line 20)

Я перепробовал все, что мог, но это всегда заканчивалось кратер sh. Я действительно понятия не имею о том, что вызывает это. Это всегда делает sh в тот момент, когда я пытаюсь деактивировать соединение (строка 93) как раз перед строкой:

clipBoard->setText(messageRecu); (line 94)

Идея состоит в том, что я не хочу соединение, когда это сама программа это меняет буфер обмена.

Кто-нибудь может мне помочь с тем, почему он выходит из строя?

Вот .h:

#ifndef FENCLIENT_H
#define FENCLIENT_H

#include <QtWidgets>
#include <QtNetwork>
#include <QClipboard>
#include "ui_fenclient.h"


class FenClient : public QWidget, private Ui::FenClient
{
    Q_OBJECT

    public:
        FenClient();

    private slots:
        void on_boutonConnexion_clicked();
        void on_boutonEnvoyer_clicked();
        void on_message_returnPressed();
        void donneesRecues();
        void connecte();
        void deconnecte();
        void erreurSocket(QAbstractSocket::SocketError erreur);
        void copiage();

    private:
        QTcpSocket *socket; // Représente le serveur
        quint16 tailleMessage;
        QClipboard *clipBoard;

};


#endif // FENCLIENT_H

Вот. cpp

#include "fenclient.h"

using namespace std;
#include<iostream>
#include <ostream>//sinon cout marche pas

FenClient::FenClient()
{
    setupUi(this);

    socket = new QTcpSocket(this);
    connect(socket, SIGNAL(readyRead()), this, SLOT(donneesRecues()));
    connect(socket, SIGNAL(connected()), this, SLOT(connecte()));
    connect(socket, SIGNAL(disconnected()), this, SLOT(deconnecte()));
    connect(socket, SIGNAL(error(QAbstractSocket::SocketError)), this, SLOT(erreurSocket(QAbstractSocket::SocketError)));

    tailleMessage = 0;

    QClipboard *clipBoard = QGuiApplication::clipboard();//Ca a été long mais il me faut ca...pas tout compris
    connect(clipBoard, SIGNAL(dataChanged()), this, SLOT(copiage()));
}

// Tentative de connexion au serveur
void FenClient::on_boutonConnexion_clicked()
{
    // On annonce sur la fenêtre qu'on est en train de se connecter
    listeMessages->append(tr("<em>Tentative de connexion en cours...</em>"));
    boutonConnexion->setEnabled(false);

    socket->abort(); // On désactive les connexions précédentes s'il y en a
    socket->connectToHost(serveurIP->text(), serveurPort->value()); // On se connecte au serveur demandé
}

// Envoi d'un message au serveur
void FenClient::on_boutonEnvoyer_clicked()
{
    QByteArray paquet;
    QDataStream out(&paquet, QIODevice::WriteOnly);

    // On prépare le paquet à envoyer
    QString messageAEnvoyer = message->text();//on enlève tr("<strong>") + pseudo->text() +tr("</strong> : ") +

    out << (quint16) 0;
    out << messageAEnvoyer;
    out.device()->seek(0);
    out << (quint16) (paquet.size() - sizeof(quint16));

    socket->write(paquet); // On envoie le paquet

    message->clear(); // On vide la zone d'écriture du message
    message->setFocus(); // Et on remet le curseur à l'intérieur
}

// Appuyer sur la touche Entrée a le même effet que cliquer sur le bouton "Envoyer"
void FenClient::on_message_returnPressed()
{
    on_boutonEnvoyer_clicked();
}

// On a reçu un paquet (ou un sous-paquet)
void FenClient::donneesRecues()
{
    /* Même principe que lorsque le serveur reçoit un paquet :
    On essaie de récupérer la taille du message
    Une fois qu'on l'a, on attend d'avoir reçu le message entier (en se basant sur la taille annoncée tailleMessage)
    */
    QDataStream in(socket);

    if (tailleMessage == 0)
    {
        if (socket->bytesAvailable() < (int)sizeof(quint16))
             return;

        in >> tailleMessage;
    }

    if (socket->bytesAvailable() < tailleMessage)
        return;


    // Si on arrive jusqu'à cette ligne, on peut récupérer le message entier
    QString messageRecu;
    in >> messageRecu;

    // On affiche le message sur la zone de Chat
    listeMessages->append(messageRecu);


    //clipBoard->disconnect();
    //const QSignalBlocker blocker(clipBoard);
    //on met dans le clipBoard
    cout << "Avant " << endl;
    bool oldState = clipBoard->blockSignals(true);
    clipBoard->setText(messageRecu);
    clipBoard->blockSignals(oldState);
    cout << "Après " << endl;

    //connect(clipBoard, SIGNAL(dataChanged()), this, SLOT(copiage()));


    // On remet la taille du message à 0 pour pouvoir recevoir de futurs messages
    tailleMessage = 0;
}

// Ce slot est appelé lorsque la connexion au serveur a réussi
void FenClient::connecte()
{
    listeMessages->append(tr("<em>Connexion réussie !</em>"));
    boutonConnexion->setEnabled(true);
}

// Ce slot est appelé lorsqu'on est déconnecté du serveur
void FenClient::deconnecte()
{
    listeMessages->append(tr("<em>Déconnecté du serveur</em>"));
}

// Ce slot est appelé lorsqu'on que le presse-papiers change
void FenClient::copiage()
{   cout << "Copiage= " << endl;
/*    QString textCopie;
    textCopie = clipBoard->text();


    QByteArray paquet;
    QDataStream out(&paquet, QIODevice::WriteOnly);

    // On prépare le paquet à envoyer
    QString messageAEnvoyer = textCopie;

    out << (quint16) 0;
    out << messageAEnvoyer;
    out.device()->seek(0);
    out << (quint16) (paquet.size() - sizeof(quint16));

    socket->write(paquet); // On envoie le paquet

    //message->clear(); // On vide la zone d'écriture du message
    //message->setFocus(); // Et on remet le curseur à l'intérieur */

}



// Ce slot est appelé lorsqu'il y a une erreur
void FenClient::erreurSocket(QAbstractSocket::SocketError erreur)
{
    switch(erreur) // On affiche un message différent selon l'erreur qu'on nous indique
    {
        case QAbstractSocket::HostNotFoundError:
            listeMessages->append(tr("<em>ERREUR : le serveur n'a pas pu être trouvé. Vérifiez l'IP et le port.</em>"));
            break;
        case QAbstractSocket::ConnectionRefusedError:
            listeMessages->append(tr("<em>ERREUR : le serveur a refusé la connexion. Vérifiez si le programme \"serveur\" a bien été lancé. Vérifiez aussi l'IP et le port.</em>"));
            break;
        case QAbstractSocket::RemoteHostClosedError:
            listeMessages->append(tr("<em>ERREUR : le serveur a coupé la connexion.</em>"));
            break;
        default:
            listeMessages->append(tr("<em>ERREUR : ") + socket->errorString() + tr("</em>"));
    }

    boutonConnexion->setEnabled(true);
}


1 Ответ

4 голосов
/ 20 января 2020

В своем определении конструктора вы написали:

QClipboard *clipBoard = QGuiApplication::clipboard(); // Bad because it shadows FenClient::clipBoard

Вместо этого вы должны были написать:

clipBoard = QGuiApplication::clipboard();

Поскольку clipBoard является членом поля вашего FenClient класса Почему вы пытаетесь объявить другую локальную переменную с тем же именем уже существующей (которая, вероятно, останется неинициализированной)?

На самом деле, это, вероятно, причина сбоя clipBoard::blockSignals(). Вы затеняли свой элемент поля clipBoard. Другими словами, он никогда не был инициализирован.

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

Я не прочитал весь ваш код, поэтому он может содержать другие проблемы.


Примечание:

Чтобы удалить соединение, лучше использовать метод QObject::disconnect().

Это позволяет вам быть более точным / конкретным c (о том, какие соединения удалить, ...). QObject::blockSignals() не дает вам такой детализации, так как блокирует все соединения.

Другое дело, вы должны прекратить использовать старые макросы SIGNAL() и SLOT() и использовать новый синтаксис слота сигнала вместо.

Итак, в вашем случае соединение будет выглядеть примерно так:

connect(clipBoard, &QClipboard::dataChanged, this, &FenClient::copiage);

И отключение симметрии c:

disconnect(clipBoard, &QClipboard::dataChanged, this, &FenClient::copiage);

Примечание QObject::disconnect() действительно удаляет соединение, поэтому, если вы хотите восстановить его, вам нужно будет восстановить его, снова вызвав QObject::connect().

...