Now I have this code:
requester.h
#ifndef REQUESTER_H
#define REQUESTER_H
#include <QtNetwork/QNetworkAccessManager>
#include <QtNetwork/QNetworkReply>
#include <QtCore/QtCore>
#include <QVector>
#include <QObject>
class Requester
{
Q_OBJECT
public:
Requester();
~Requester();
QString get_last_reply();
void send_request();
private:
QNetworkAccessManager *manager;
QVector<QString> replies;
public slots:
void get_reply(QNetworkReply *reply);
};
#endif // REQUESTER_H
requester.cpp
#include "requester.h"
Requester::Requester()
{
manager = new QNetworkAccessManager;
}
Requester::~Requester() {
delete manager;
}
void Requester::get_reply(QNetworkReply *reply) {
QByteArray res = reply->readAll();
QString data = res.data();
replies.push_back(data);
}
QString Requester::get_last_reply() {
QString res = replies.back();
replies.pop_back();
return res;
}
void Requester::send_request() {
QObject::connect(manager, SIGNAL(finished(QNetworkReply*)), this, SLOT(get_reply(QNetworkReply*)));
manager->get(QNetworkRequest(QUrl("http://google.com")));
}
And this error:
no matching function for call to 'QObject::connect(QNetworkReply*&, const char*, Requester* const, const char*)'
What's wrong? I've tried to use just connect instead of QObject::connect, but there was an error about the impossibility of converting QNetworkAccessmanager to socket.
The problem is that you are not inheriting QObject, so naturally: you cannot get slots handled in that class.
You should write something like this:
requester.h
class Requester : public QObject
{
Q_OBJECT
public:
explicit Requester(QObject *parent);
...
requester.cpp
#include "requester.h"
Requester::Requester(QObject *p)
: QObject(p)
, manager(new QNetworkAccessManager)
{
}
...
Also, there is little to no point in this case to construct the QNetworkAccessManager on the heap as opposed to the stack. You could just have a QNetworkAccessManager m_networkAccessManager; member without the allocation, construction, and deletion, but this is just an additional information for the future.
Related
Im trying to make a request to get some data with QT.
my backend.h
#ifndef BACKEND_H
#define BACKEND_H
#include <QNetworkAccessManager>
#include <QObject>
#include <QString>
#include <QNetworkReply>
class BackEnd : public QObject
{
Q_OBJECT
Q_PROPERTY(QString userName READ userName WRITE setUserName NOTIFY userNameChanged)
public:
explicit BackEnd(QObject *parent = nullptr);
QString userName();
void setUserName(const QString &userName);
signals:
void userNameChanged();
private:
QString m_userName;
QNetworkAccessManager *manager;
//also tried: void RequestReceived(QNetworkReply* reply); << without space after QNetworkReply
void RequestReceived(QNetworkReply * reply);
};
#endif // BACKEND_H
my .cpp
#include "backend.h"
#include <string>
#include <iostream>
#include <QtNetwork>
BackEnd::BackEnd(QObject *parent) :
QObject(parent)
{
manager = new QNetworkAccessManager(this);
}
void BackEnd::RequestReceived(QNetworkReply * reply){
QByteArray rawData = reply->readAll();
QString textData(rawData);
qDebug() << textData;
}
QString BackEnd::userName()
{
return m_userName;
}
void BackEnd::setUserName(const QString &userName)
{
if (userName == m_userName)
return;
m_userName = userName;
connect(manager, SIGNAL(finished(QNetworkReply*)),
this, SLOT(RequestReceived(QNetworkReply*)));
manager->get(QNetworkRequest(QUrl("https://google.com")));
emit userNameChanged();
}
I found similair questions but almost all answers say Q_OBJECT should be added (which I have). Im very new to qt but if I understand correctly the error indicates that I do not have a
BackEnd::RequestReceived(QNetworkReply*)
method, which I do have. Any help is welcome.
You need to mark void RequestReceived(QNetworkReply * reply); as a slot:
Q_SLOT void RequestReceived(QNetworkReply * reply);
I am trying to get text from a website using the QNetworkAccessManager class, but it's not working. When the replyFinished slot above is called, the parameter it takes is the QNetworkReply object containing the downloaded data as well as meta-data (headers, etc.). When the slot gets called, I append the gotten text to a QString and print it out, but it prints an empty string. Here is my code:
//.pro file
TEMPLATE = app
QT += qml quick
QT += network
CONFIG += c++11
//xmlparser.h
#ifndef XMLPARSER_H
#define XMLPARSER_H
#include <QObject>
#include <QNetworkAccessManager>
class XMLParser : public QNetworkAccessManager
{
Q_OBJECT
public:
~XMLParser()=default;
static XMLParser &Instance();
Q_INVOKABLE void readXML();
signals:
finished(QNetworkReply* reply);
public slots:
void replyFinished(QNetworkReply* reply);
private:
XMLParser()=default;
XMLParser(XMLParser const&)=delete;
void operator = (XMLParser const&)=delete;
QByteArray m_text;
};
#endif // XMLPARSER_H
//xmlparser.cpp
#include <QUrl>
#include <QDebug>
#include <QNetworkAccessManager>
#include <QNetworkRequest>
#include <QNetworkReply>
#include <QEventLoop>
#include "xmlparser.h"
XMLParser &XMLParser::Instance()
{
static XMLParser instance;
return instance;
}
void XMLParser::readXML()
{
QNetworkAccessManager *manager = new QNetworkAccessManager(this);
connect(manager, SIGNAL(finished(QNetworkReply*)),
this, SLOT(replyFinished(QNetworkReply*)));
manager->get(QNetworkRequest(QUrl("http://qt-project.org")));
}
void XMLParser::replyFinished(QNetworkReply *reply)
{
QString text;
text.append(reply->readAll());
qDebug () << "Text: " << text; //Prints out emtpy string?
}
I'd like to add some QT example code to my simple project. The sample code is here: https://wiki.qt.io/Download_Data_from_URL
It consists of filedownloader.cpp and filedownloader.h -- this code downloads a graphic from a supplied URL.
I've added these files to my project and get a clean compile. I think I understand the code ok (I'm mainly a c coder, not c++) but I don't understand how I can pass the QUrl created by my project to filedownloader.cpp
The "project" is just a simple main.cpp/mainwindow.cpp/mainwindow.ui that offers a button to be pressed. Pressing the button calls the routine below:
void MainWindow::on_pushButton_clicked()
{
// pass to filedownloader to process
QUrl fileloc("http://www.test.com/test.jpg");
}
How do I feed the QUrl fileloc to filedownload.cpp?
You have to add a new method to FileDownloader, that accepts QUrl and starts the download.
filedownloader.h:
#ifndef FILEDOWNLOADER_H
#define FILEDOWNLOADER_H
#include <QObject>
#include <QByteArray>
#include <QNetworkAccessManager>
#include <QNetworkRequest>
#include <QNetworkReply>
class FileDownloader : public QObject
{
Q_OBJECT
public:
explicit FileDownloader(QUrl imageUrl, QObject *parent = 0);
virtual ~FileDownloader();
QByteArray downloadedData() const;
signals:
void downloaded();
public slots:
void download(QUrl url); // <------ Here it is
private slots:
void fileDownloaded(QNetworkReply* pReply);
private:
QNetworkAccessManager m_WebCtrl;
QByteArray m_DownloadedData;
};
#endif // FILEDOWNLOADER_H
filedownloader.cpp:
#include "filedownloader.h"
FileDownloader::FileDownloader(QObject *parent) :
QObject(parent)
{
connect(
&m_WebCtrl, SIGNAL (finished(QNetworkReply*)),
this, SLOT (fileDownloaded(QNetworkReply*))
);
// <------ Notice, that i've removed downloading code from here
}
FileDownloader::~FileDownloader() { }
void FileDownloader::fileDownloaded(QNetworkReply* pReply) {
m_DownloadedData = pReply->readAll();
//emit a signal
pReply->deleteLater();
emit downloaded();
}
void FileDownloader::download(QUrl url) { // <------ And its definition
QNetworkRequest request(url);
m_WebCtrl.get(request);
}
QByteArray FileDownloader::downloadedData() const {
return m_DownloadedData;
}
And then your on_pushButton_clicked will look like this:
void MainWindow::on_pushButton_clicked()
{
// pass to filedownloader to process
QUrl fileloc("http://www.test.com/test.jpg");
m_filedownloader.download(fileloc);
}
I'm trying to get a web page using Qt and print it on the screen.The problem is it always prints "". It won't make it to the done SLOT. I don't know if there's something wrong with the connect(). The code gets compiled with no errors.
Trying not to use event loops yet.
Here's the code:
net.h
#ifndef NET_H
#define NET_H
#include <QObject>
#include <QtNetwork>
#include <QString>
#include <QDebug>
class net : public QObject
{
Q_OBJECT
public:
explicit net(QObject *parent = 0);
void get_site(QString url);
QString data;
signals:
public slots:
void err(QNetworkReply *);
void done(QNetworkReply *);
private:
};
#endif // NET_H
net.cpp:
#include "net.h"
net::net(QObject *parent) :
QObject(parent)
{
}
void net::get_site(QString url) {
QNetworkAccessManager man;
QNetworkRequest request;
request.setUrl (QUrl(url));
connect (&man , SIGNAL(finished(QNetworkReply*)) ,this, SLOT(done(QNetworkReply*)));
connect (&man , SIGNAL(finished(QNetworkReply*)) ,this, SLOT(err(QNetworkReply *)));
man.get (QNetworkRequest(QUrl(url)));
}
void net::done(QNetworkReply * reply) {
data = QString(reply->readAll ());
}
void net::err(QNetworkReply * reply) {
data = QString(reply->errorString ());
}
And main.cpp:
#include <QCoreApplication>
#include "net.h"
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
net netobj;
netobj.get_site("http://stackoverflow.com");
qDebug() << netobj.data;
return a.exec();
}
There are some major problems in your code. First you should have the QNetworkAccessManager as a class member in .h file :
class net : public QObject
{
...
private:
QNetworkAccessManager nam;
};
Also you should not connect the finished signal to two different slots. Your get_site function should be like :
void net::get_site(QString url) {
QNetworkRequest request;
request.setUrl (QUrl(url));
connect (&man , SIGNAL(finished(QNetworkReply*)) ,this, SLOT(done(QNetworkReply*)));
man.get (QNetworkRequest(QUrl(url)));
}
And you should manage the returned reply in the following way :
void net::done(QNetworkReply * reply) {
if (reply->error() == QNetworkReply::NoError)
{
data = QString(reply->readAll ());
}
else
{
data = QString(reply->errorString ());
}
}
Your QNetworkAccessManager instance goes out of scope at the end of your get_site function. According to Qt docs, one QNetworkAccessManager should be enough for the whole Qt application. Your object should persist outside the scope of that function, since it's likely the response will take longer to receive than it will take for that function to end. Make the QNetworkAccessManager a member of your net class, instead of an automatic variable local to get_site.
Note that you also need to manage the lifetime of the QNetworkReply object, not by using delete, but by using deleteLater() or else you might leak memory.
After debugging, I'm sure that the replyFinish() slot is not called when I call this->getNetReply(). These are my files, in the main() fumction I call the getNetReply this way: Networking a; a.getNetReply();
I did add QT+=network to my qmake.
Please help me. Thank you very much.
my networking.cpp file
#include "networking.h"
#include <QUrl>
#include <QNetworkRequest>
// constructor
void Networking::getNetReply(){
QNetworkAccessManager *man = new QNetworkAccessManager(this);
QObject::connect(man, SIGNAL(finished(QNetworkReply *)), this, SLOT(replyFinished(QNetworkReply *)));
qDebug() << "connected";
QNetworkRequest req;
req.setUrl(QUrl("http://www.google.com"));
man->get(req);
}
// this method not called
void Networking::replyFinished(QNetworkReply *reply){
QByteArray data = reply->readAll();
QString str = QString(data);
this->netRep = str;
code = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();
}
my networking.h header file:
#ifndef NETWORKING_H
#define NETWORKING_H
#include <QObject>
#include <QNetworkAccessManager>
#include <QNetworkReply>
class Networking : public QObject
{
Q_OBJECT
public:
QString netRep;
int code;
explicit Networking(QObject *parent = 0);
void getNetReply();
public slots:
void replyFinished(QNetworkReply*);
};
#endif // NETWORKING_H
The get() function returns a QNetworkReply object. Connect to the error signal of that object and it will tell you if an error happens (and which).