Краткий обзор того, что происходит: я пытаюсь выполнить запрос GET, используя Qt QNetworkAccessManager
, но функция обратного вызова на моем QObject::connect(..)
функция не вызывается. Мои вопросы я могу позвонить QObject::connect
от одного объекта, но подключиться к слоту другого объекта (учитывая, что у меня есть указатель как на объект, так и на слот) — подробности см. ниже.
Моя конечная цель состоит в том, чтобы POST-данные (видя, что это функция входа в систему), у меня был код POST-запроса, который в конечном итоге страдал от той же проблемы — функция обратного вызова не вызывается. Поэтому я хотел бы сначала выполнить простой запрос GET, как только он у меня появится, я думаю, что все будет в порядке самостоятельно.
В настоящее время у меня есть QMainWindow LoginWindow
, с кнопкой, которая вызывает слот doLogin()
в классе LoginWindow. Это все работает, как и следовало ожидать. LoginWindow также имеет public slots
функция называется loginResponse(QNetworkReply* response)
,
//---LoginWindow.h
...
public slots:
void doLogin();
void loginResponse(QNetworkReply* response)
...
//---LoginWindow.cpp
LoginWindow::LoginWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::LoginWindow)
{
ui->setupUi(this);
ui->username_le->setFocus();
}
void LoginWindow::doLogin()
{
MyProduct::Network network(this);
qDebug() << "Logging in...";
//Here I call network.login from LoginWindow and pass
//references to the Slot I want to use and the LoginWindow itself
network.login(
ui->username_le->text(), //username
ui->password_le->text(), //password
this, //reference to this object (LoginWindow*)
SLOT(loginResponse(QNetworkReply*)) //loginResponse slot
);
}
void LoginWindow::loginResponse(QNetworkReply* response)
{
qDebug() << "Log in complete";
}
Далее у меня есть другой класс, под MyProduct
пространство имен, называется Network
, Как вы можете видеть выше, Network
имеет функцию входа в систему Вот:
void MyProduct::Network login(QString username, QString password, QObject *receiver, const char *slot)
{
QNetworkRequest request(QUrl(API_ROOT + LOGIN_PATH)); //"http://localhost/basic/login.php"request.setHeader(QNetworkRequest::ContentTypeHeader,"application/x-www-form-urlencoded");
//nam = QNetworkAccessManager* declared in the constructor
QObject::connect(nam,SIGNAL(finished(QNetworkReply*)), receiver, slot);
qDebug() << "Posting login data...";
nam->get(request);
}
Целью здесь является создание функции входа в мой Network
класс, который можно использовать и подключать в любом количестве окон (поскольку пользователи могут входить в систему из разных мест). Но я не получаю ответа — LoginWindow::loginResponse
не запускается.
В консоли отображается сообщение «Вход в систему …» и «Публикация данных для входа в систему», но не «Вход в систему завершен».
Кто-нибудь может указать мне правильное направление или сказать, что я сумасшедший или это плохая идея?
Заранее спасибо!
Обратите внимание, что QNetworkAccessManager
работает асинхронно. get()
метод не блокируется во время работы сети; это возвращается немедленно. (См. Подробное описание раздел документации для получения дополнительной информации.)
Это довольно типично для связанных с сетью API-интерфейсов Qt, потому что вы обычно не хотите, чтобы ваше приложение зависало в ожидании перемещения данных по сети.
Что это означает, что ваш экземпляр, nam
, не существует достаточно долго, чтобы запрос GET действительно завершился. Ваш экземпляр Product::Network
класс удаляется сразу после вызова login()
потому что он расположен в стеке. Хотя я не вижу код, я думаю, он очищает QNetworkAccessManager
также.
Если вы продлите срок службы вашего network
объект, вы можете обнаружить, что ваш слот в конечном итоге будет вызван.
Кроме того, это больше вопрос предпочтений, но я думаю, что было бы чище, чтобы избежать передачи ресивера и слота на ваш login()
функция. Я бы порекомендовал объявить ваши собственные сигналы в Network
класс как часть его API, и для подключения к тем в LoginWindow
учебный класс.
Других решений пока нет …