Solved Adding example code to existing project
-
I've created a working project with QT Creator and I'd like to add the ability to download from an url to it.
I've read the code here:
https://wiki.qt.io/Download_Data_from_URL
I'm confused as to how I add this code to my existing project.
-
Hi, welcome to Devnet,
Could you tell us what is the purpose of your project?
Here is another example:
http://doc.qt.io/qt-5/qtnetwork-downloadmanager-example.html
I'm affraid you'll have to understand the code since there is no explanation or whatsoever, but we are here to help you.First, you have to add the Network library in your .pro file (or CMake), then create class(es) to download things from URLs using signal/slot (since downloading is done asynchronously) and finally call the download from the rest of your program.
Depending on what your project is, the integration can be even more simple.
Don't hesitate to post some relevant code here too.
-
I haven't done any significant code yet. I just have a one window program with a button UI. I'm used to working in c, c++ noob, just starting out. Thanks for the reply!
-
OK, I've added the filedownloader.h & filedownloader .cpp files to my project, and included filedownloader.h in my mainwindow.cpp file. I'm getting a clean compile.
Now in my button's
void MainWindow::on_pushButton_clicked()
{}
needs to pass a QUrl to filedownloader.cpp for download.
filesFileDownloader::FileDownloader(QUrl imageUrl, QObject *parent) : QObject(parent)
How do I pass that url to filedownloader.cpp?
-
From where do you get the URL?
-
@Jedd
It's hard to tell without the rest of the code, but I'm assuming that when you press your button, in the MainWindow, you have access to at least some kind of text representing your image URL, right? If so, you may have to create a FileDownloader as well as a QURL. Then call the method that downloads the image, and treat responses.It'd be helpful if you provided us with your code.
P.S.: are you familiar with Qt? Especially its signal/slot programming?
-
@ValentinMichelet
"It'd be helpful if you provided us with your code. P.S.: are you familiar with Qt? Especially its signal/slot programming?"No, I'm new to OOP, I've only coded in C. My code is very simplistic. It's merely a window with a button. The code does cleanly compile.
https://wiki.qt.io/Download_Data_from_URL
The link above contain filedownloader.cpp + its header. They are both included currently unchanged to my program.
main.cpp
#include "mainwindow.h"
#include <QApplication>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MainWindow w;
w.show();
return a.exec();
}mainwindow.cpp
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include "filedownloader.h"MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
}MainWindow::~MainWindow()
{
delete ui;
}void MainWindow::on_pushButton_clicked()
{
QString fileloc = "http://www.test.com/test.jpg";
// pass to filedownloader to process
} -
OK, so what is in your UI file? You will need at least a button whose clicked() signal is connected to your on_pushButton_clicked() slot, as well as a line edit to let the user enters an URL. Then in the on_pushButton_clicked() method, you will get this text, create a QUrl, create a file downloader from this QUrl and treat asynchronously the file downloader response, thanks to SIGNAL/SLOT mechanisms.
Let me know when you are stuck.
-
void MainWindow::on_pushButton_clicked()
{
// pass to filedownloader to process
QUrl fileloc("http://www.test.com/test.jpg");}
Thanks for the reply. As you see above, the QUrl fileloc is created when the UI's button is pressed. How do I pass this QUrl to fildeownloader.cpp?
-
OK, so it's harcoded for now, but it will be dynamic in a next version, right? You will have to hardcode it in your constructor tho, since you need to create a member variable that will be used accross your MainWindow. For a smarter version, when the URL won't be hardcoded anymore - but got from a user input - you will have to change your code, especially the FileDownloader mechanisms.
Well, if you look at your filedownloader.h you have the declaration for your constructor:
public: explicit FileDownloader(QUrl imageUrl, QObject *parent = 0);
So first, in your h file, if you haven't done yet, add a member variable that is a pointer to FileDownloader:
private: FileDownloader* m_fileDownloader;
Then, in your cpp file, just create this FileDownloader on the heap (with 'new') giving your QUrl as its first parameter, 'this' as its second parameter.
MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWindow) { ui->setupUi(this); QUrl fileloc("http://www.test.com/test.jpg"); m_fileDownloader = new FileDownloader(fileloc, this); }
The fileloc will be used in the FileDownloader to download the corresponding image. The 'this' parameter is used for memory handling. Since you know C, it's not a big surprise that you have to handle dynamic memory allocation. But Qt has created a way to make your life easier. Indeed, when you create a class that inherits somewhere from QObject, you can give it a parent. The destructors called in cascade will free the memory for you, no need to delete or set to nullptr anymore on these objects.
Let's finish with the download. Here you have to understand that some actions are done asynchronously. This means that the program will execute some lines in parallel. Especially, since a download can take some time, it's done in parallel, while your application keep on running. Otherwise, it would freeze, and you would have to wait until the download is done, which, according to the network, can take a while!
Here the SIGNAL/SLOT mechanism is helpful. Your FileDownloader will warn you as soon as the download is done, thanks to the downloaded() signal. You have to connect this signal to a custom slot that will do stuff with your downloaded image, but only when the download is done. In the example, it will display it in a QLabel, but you can do whatever you want.To achieve that, first, you will declare a slot in your h file:
private slots: // This won't be called from outside, hide it. void imageDownloaded();
Thus, you can connect it with the FileDownloader signal in your constructor:
MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWindow) { ui->setupUi(this); QUrl fileloc("http://www.test.com/test.jpg"); m_fileDownloader = new FileDownloader(fileloc, this); connect(m_fileDownloader, SIGNAL(downloaded()), this, SLOT(imageDownloaded())); }
And finally, create the slot in your cpp file:
void MainWindow::imageDownloaded() { // Get your image QByteArray imageData = m_fileDownloader->downloadedData(); // Do stuff with your data }
Now, you understand why we need a member variable: we are using a single object in different methods. Note that you get a QByteArray, that you can use to create a QPixmap, a QString... depending on what you are downloading.
Try to understand what I explained here, it's a lot to process, and come back here if you want more details, new information, or improve your program.
-
Wow, so cool. I learned a lot here, Thanks!