Qt - Connecting C++ and QML - ReferenceError: xxx is not defined - c++

I am new to Qt and am currently trying to connect a c++ part of my program with the qml part. The goal of th connection is to pass the currently selected item of a TreeView to qml (possibly via on_treeView_doubleClicked). Since that didnt work I tried all the suggested connections on here for a very basic programm, but I am always receiving the following error:
file::/main.qml:10: ReferenceError: test is not defined
This is the piece of my code regarding the connection:
test.h:
#ifndef TEST_H
#define TEST_H
#include <QObject>
#include <QDebug>
class test : public QObject
{
Q_OBJECT
public:
explicit test(QObject *parent = nullptr);
Q_INVOKABLE void testFunc();
signals:
public slots:
};
#endif // TEST_H
test.cpp:
#include "test.h"
test::test(QObject *parent) : QObject(parent)
{
}
void test::testFunc()
{
qDebug() << "Hello from C++!";
}
mainwindow.cpp:
test testObj;
QQmlApplicationEngine engine;
ui->quickWidget->setSource(QUrl::fromLocalFile(":/main.qml"));
engine.rootContext()->setContextProperty("test", &testObj);
main.qml:
import QtQuick 2.0
import QtQuick.Window 2.3
Item {
Timer{
id: timer
interval: 1000; running: true; repeat:true
onTriggered:{
console.log("ex")
test.testFunc();
}
}
}
I would be really thankful for any help (not only for the simple programm, but possibly for passing the currently selected item of my treeView). I know there a a couple suggestions in other threads, but they dont seem to work for me, so please dont mark this as duplicate.
Thanks in advance,
Lucas

You have 3 main errors:
If you are going to use a .qml from a qresource you should not use QUrl::fromLocalFile() since the qresource is not a local file but virtual.
testObj is a local variable so it will be eliminated as soon as the function where it was created is finished, one solution is to make testObj a member of the class.
And for the last one, the main error, QQuickWidget already has a QQmlEngine, you do not have to create another one.
*.h
Ui::MainWindow *ui;
test testObj;
*.cpp
ui->quickWidget->setSource(QUrl("qrc:/main.qml"));
ui->quickWidget->engine()->rootContext()->setContextProperty("test", &testObj);
My full test can be found at the following link

Related

Accessing Qt GUI ui from another class OR using connect() to update gui elements

I need some help understanding how to access the QT GUI ui from another class/another cpp file.
Background: I am working on a project that consists of many cpp and hpp files. I am not the original author. This project is to control a USRP to receive/send data....with various parameters. Originally, you had to manually change parameter values inside several cpp files (i..e start frequency, steps, duration of receive, etc). Then re-compile and then run the executable. I wrote a simple Qt GUI interface in the main.cpp function where the users would enter in the GUI basic usrp receive parameters. Then the GUI interface would pass these values back into the uspr function that would actually execute the USRP functionality. This part is actually working great and I am happy (my first GUI!, Yay!)
One thing that I would like to do is to also display the current frequency in the main GUI window via the LCDNumber widget. This frequency is managed by another class, in another cpp file.
Here is what I tried:
Attempt #1: Make the MainWindow ui publicly available int the class/cpp file where the Frequency is established:
freq_transmit.cpp:
......
#include "mainwindow.hpp"
#include "ui_mainwindow.hpp"
.....
void Receiver::run()
{
//bunch of lines of code about USRP stuff
.....
rxCenterFreq // <---variable that holds the current frequency (which changes every second)
ui->lcdnumber->display(rxCenterFreq); // <-- -compiler error: ui not declared in this scope
............
mainwindow.h:
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include <QtCore>
#include <QCoreApplication>
#include <QPalette>
QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
QT_END_NAMESPACE
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
MainWindow(QWidget *parent = nullptr);
~MainWindow();
Ui::MainWindow *ui;
QPalette temp_red;
QPalette temp_green;
private slots:
void on_button_CalcSchedule_clicked();
void on_button_Reset_clicked();
void execute_run_usrp();
void on_button_QUIT_clicked();
void on_AutoSchedulerCheckBox_stateChanged(int arg1);
void on_button_manul_CalcSchedule_clicked();
void on_button_EXECUTE_clicked();
void on_button_SeeSchedule_clicked();
void on_button_STOP_clicked();
void function_test();
public slots:
void updateTXFreq(double a);
private:
void reset_sweep_values();
std::string calc_schedule_start_time(int minute_cadence);
void calc_cadence();
double calc_sweep_duration();
int nearest_cadence(int numToRound, int multiple);
signals:
void send_start_schedule(std::string, double, int, int);
};
#endif // MAINWINDOW_H
Attempt #2: Use Qt CONNECT functionality:
Step 1: generate a SIGNAL / emit function in the freq_transmit.hpp header:
....
signals:
void sendTXFreq(double a);
Step 2: Enter this emit signal in the freq_transmit.cpp file where the Frequency is being generated:
freq_transmit.cpp:
......
#include "mainwindow.hpp"
#include "ui_mainwindow.hpp"
.....
void Receiver::run()
{
//bunch of lines of code about USRP stuff
.....
emit sendTXFreq(rxCenterFreq); // emit signal to QT
....
Step 3: Declare a SLOT in mainwindow.h to accept emitted signal
mainwindow.hpp:
...
public slots:
void updateTXFreq(double a);
Step 4: Implementation:
mainwindow.cpp:
....
void MainWindow::updateTXFreq(double a)
{
ui->lcdnumber->display(a);
}
connect(&Receiver, &Receiver::sendTXFreq, this, &MainWindow::updateTXFreq); // <-- error: expected primary expression before ','
which is the comma after "&Receiver", which is a class that has various functions in it, including the Receiver::run() where Frequency is generated.`
Long story short, I am trying to have the generated frequency linked to a LCDNumber widget so that it shows on the GUI the value of frequency as the USRP code runs.
PS: I am not an expert C++ coder, I am just now learning about classes and QT GUI. Somebody mentioned that I should "create a pointer of my MainWindow in the freq_transmit.cpp file" so that then I can accesss ui elements direclty in that class, but I thought I tried that with ui->lcdnumber->display(rxCenterFreq);
Any guidance much appreciated and thank you!

Building Qt project with CMake and inheriting from QMainWindow leads to unreferenced vtable error

This is about a Qt 5.3.2 project buildt using CMake.
I have designed a QMainWindow using the Qt Designer, leading
to main.ui.
CMakeLists.txt (the almost complete thing may be
found here where I already posted it for a different question:
Linking and UIC order in a CMake Qt project )
already takes care of calling UIC so I have my hands on ui_main.h.
ui_main.h offers the class Ui::MainWindow with the plain form information
where all the buttons and stuff should be and the method *void setupUi(QMainWindow MainWindow).
Now my workflow (is it even a feasible one?) goes like this:
I build a totally new header file Form_main.h:
// Form_main.h
[..]
class Form_main : public MainWindow, public QMainWindow
{
Q_OBJECT
privat slots:
void on_some_event();
[..]
};
The class uses said auto-generated MainWindow::setupUi(this) to 'get in shape' and QMainWindow to be, well, a QMainWindow with all that stands for.
But now I am in a dilemma: Either I remove the Q_OBJECT macro call leading to connect(..) no longer recognizing that Form_main has signal slots, or
I keep the Q_OBJECT leading to the infamous
undefined reference to `vtable for display::Form_main'
error while linking the project.
Now, there have been, in fact, people with similar issues.
Naming some links:
http://michael-stengel.com/blog/?p=103
Qt Linker Error: "undefined reference to vtable"
Undefined reference to vtable... Q_OBJECT macro
Qt vtable error
A hint I got from the last one: "MOC must generate code for ui_main.h and the generated code must be compiled and linked."
In any case, these answers all seem to boil down to 'running qmake again'. Well, I use CMake all the way wanting my project to configure and compile after exactly
cmake .
make
What I did try was deleting everything in and below the build directory
(including every auto-generated file) and then running cmake . && make;.
Sadly that did not help. I am afraid this is my second noob question today... would you bear with me once more?
=== AFTER TRYING GREENWAYS ANSWER I PROVIDE MORE DETAILS. ===
Here is the autogenerated ui_main.h
/********************************************************************************
** Form generated from reading UI file 'main.ui'
**
** Created by: Qt User Interface Compiler version 5.3.2
**
** WARNING! All changes made in this file will be lost when recompiling UI file!
********************************************************************************/
#ifndef UI_MAIN_H
#define UI_MAIN_H
#include <QtCore/QVariant>
#include <QtWidgets/QAction>
[.. more Widget Includes ..]
QT_BEGIN_NAMESPACE
class Ui_MainWindow
{
public:
QAction *action_exit;
[.. more sub widgets like that .. ]
void setupUi(QMainWindow *MainWindow)
{
[ .. Setting up the form. Harmless code. .. ]
} // setupUi
void retranslateUi(QMainWindow *MainWindow)
{
[ .. completely harmless .. ]
} // retranslateUi
};
namespace Ui {
class MainWindow: public Ui_MainWindow {};
} // namespace Ui
QT_END_NAMESPACE
#endif // UI_MAIN_H
Reading all this and incorporating your post right now I am at
// form_main.h
#ifndef MHK_FORM_MAIN_H
#define MHK_FORM_MAIN_H
#include <QMainWindow>
#include "ui_main.h"
[..]
namespace Ui { class MainWindow; }
namespace display
{
class Form_main : public QMainWindow
{
Q_OBJECT
private:
ostream* stdout;
ostream* stderr;
Ui::MainWindow* uiMainWindow;
/** Called by the constructor. Sets up event connections and other
* preliminary stuff the qt Designer is overtasked with. */
void setup_form();
[..]
public:
explicit Form_main(QWidget* parent = 0);
~Form_main();
private slots:
void exit_program();
};
}
#endif
And my cpp
// form_main.cpp
#include "ui_main.h"
#include "form_main.h"
[..]
using namespace Ui;
namespace display
{
void Form_main::setup_form()
{
QObject::connect(uiMainWindow->action_exit, SIGNAL(triggered()), this, SLOT(exit_program()));
[..]
}
Form_main::Form_main(QWidget* parent) : QMainWindow(parent)
{
uiMainWindow = new Ui::MainWindow();
uiMainWindow->setupUi(this);
[..]
#if defined(Q_OS_SYMBIAN)
this->showMaximized();
#else
this->show();
#endif
}
Form_main::~Form_main()
{
delete uiMainWindow;
}
[..]
Form_main::exit_program()
{
this->close();
(*stdout) << "Thanks for playing " << getProgramName() << endl;
}
}
Ok. I see (partly) the problem. Just create a widget class like this:
.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
namespace Ui {
class MainWindow;
}
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();
private:
Ui::MainWindow *ui;
};
#endif // MAINWINDOW_H
.cpp
#include "MainWindow.h"
#include "ui_MainWindow.h"
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
}
MainWindow::~MainWindow()
{
delete ui;
}
This is how the QtCreator creates ui-Widgets. "ui_MainWindow.h" is your generated .h file.
Thanks for all your help! However, the problem was in CMakeLists.txt after all. The comment of Chris Morlier on Undefined reference to vtable pointed me to the solution.
The pertinent passage goes:
For Qt users: you can get this same error if you forget to moc a header
I simply had to add the header form_main.h into this line:
QT5_WRAP_CPP(qt_H_MOC ${qt_H} "${DIR_SRC}/include/form_main.h")

qt4 designer add custom class

Hi i have made a gui in qt4 designer and want to add custom slots with custom class.
It project compiles nicely without errors but my custom function wont work what am i doing wrong? I will show u the header file qt4 designer made for me and ill show u my custom file as well as the main.cpp.. first the main.cpp
I have revised my code, here is what i have now i have added a file called sweetest.cpp and edited the sweetest.h here are my new file and the error i recieve..
First main.cpp
#include "ui_sweetguiform.h"
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
QWidget *widget = new QWidget;
Ui::SweetGuiForm ui;
ui.setupUi(widget);
widget->show();
return app.exec();
}
now my custom header file sweetest.cpp
#include "sweetest.h"
// trying to include the .moc file wouldnt work at all.
now the sweettest.h file with my code
#include "ui_sweetguiform.h"
class SweetGuiForm : public QWidget
{
Q_OBJECT
public:
SweetGuiForm( ): ui( new Ui::SweetGuiForm )
{
ui->setupUi( this );
connect(ui->buttonBox, SIGNAL(accepted()), this, SLOT(on_buttonBox_accepted()));
}
public slots:
void on_buttonBox_accepted()
{
ui.textEdit->setText(QString::number(23));
}
protected:
Ui::SweetGuiForm* ui;
};
Here is the compile error i recieve.. I am really stuck
In file included from sweetest.cpp:1:
sweetest.h: In member function ‘void SweetGuiForm::on_buttonBox_accepted()’:
sweetest.h:16: error: request for member ‘textEdit’ in ‘((SweetGuiForm*)this)->SweetGuiForm::ui’, which is of non-class type ‘Ui::SweetGuiForm*’
make: *** [sweetest.o] Error 1
I think im getting closer
The way that signals and slots work is that you must connect a signal to a slot. In your code, the simplest way to do that is in the constructor for the SweetGuiForm. You need to add:
SweetGuiForm() : ui(new Ui::SweetGuiForm) {
ui->setupUi(this);
connect(ui->buttonBox, SIGNAL(accepted()), this, SLOT(on_buttonBox_accepted()));
}
When the buttonBox emits its accepted signal all slots connected to it will be called.
update 1
On further inspection of your code, you are also missing the Qt macros that are used by the Qt MOC (meta-object compiler) system (http://qt-project.org/doc/qt-4.8/moc.html):
class SweetGuiForm : public QWidget
{
Q_OBJECT
public:
...
};
You also have to push the code through the MOC tool. It will generate a source file that needs to be included in your source. As I recall, you must include that in a cpp file; inclusion in a header is problematic. The following should be sufficient:
sweetguiform.cpp:
#include "suiteguiform.h"
#include "sweetguiform.moc"
update 2
On further further reflection, I had forgotten about the automatic signal/slot connection feature when you name your slots using special names (such as on_buttonBox_accepted). There is a blog post on just that here: http://qtway.blogspot.com/2010/08/automatic-connections-using-qt-signals.html. I've not used it myself, so I can't comment on its ability to work when using a ui member variable, though I suspect that it does not work in that arrangement. Regardless, you still need the Q_OBJECT macro and MOC.
Ok guys i figured it out and thought ide share what i found.
First the documentation is excellent in qt4 use it.
I found you can use qt4 designer to generate the hearder files, first i complied it with out custom slots and generated the ui_sweetgui2.h, then i could open the sweetgui2.h file generated by the first compile i did delete what qt4 put in there and put my custom slots in at that stage. did my head in for hours.... days.
so here is the simplest app on earth but its got me started so here are the files and code that worked for me and the documentation basically got me to click on to whats going on.
main.cpp
Strait from the documentation just changed the class name "SweetGuiForm".
#include <QApplication>
#include "sweetgui2.h"
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
SweetGuiForm sweetgui;
sweetgui.show();
return app.exec();
}
next sweetgui2.cpp
My first attempt at c++.. ugly but works. But again i found everything about getting the text from the textEdit and type casting it to a int in the calculator example and searching for toPlainText() in the qt4 assistant. notice below im including the file that i will define the new slots that ill show further on in my explanation. hope im making sense.
#include <QtGui>
#include "sweetgui2.h"
SweetGuiForm::SweetGuiForm(QWidget *parent)
: QWidget(parent)
{
ui.setupUi(this);
}
void SweetGuiForm::on_buttonBox_accepted()
{
QString stringamount = ui.textEdit->toPlainText();
int digitamount = stringamount.toInt();
ui.textEdit->setText(QString::number(25 + digitamount));
}
next sweetgui2.h the one we included above My custom header file with my custom slot.... simple as i said from the calculator example and twisted a lil.. you will get it this is not what it looks like when you generate it from designer on the first compile this is after i have deleted nearly all what was there and opened the calculator example and followed in the tutorial wich shows you how to make your first custom slot .
#ifndef SWEETGUI2_H
#define SWEETGUI2_H
#include "ui_sweetgui2.h"
class SweetGuiForm : public QWidget
{
Q_OBJECT
public:
SweetGuiForm(QWidget *parent = 0);
private slots:
void on_buttonBox_accepted();
private:
Ui::SweetGuiForm ui;
};
#endif // SWEETGUI2_H
Again Straight from the documentation. I used the calculator example to get the basic flow.
next ui_sweetgui2.h
I include this file because i was trying to add my slots to the sweetgui2.h that was generated by qt4 desinger. doesnt work guys ..so i compiled first with sweetgui2.h file you generate with the designer, i go to forms menu then view code that is where u can save header files. then of course save the ui file.
and compile then you end up with the ui_sweetgui2.h file wich looked like the sweetgui2.h generated by the designer
#ifndef UI_SWEETGUI2_H
#define UI_SWEETGUI2_H
#include <QtCore/QVariant>
#include <QtGui/QAction>
#include <QtGui/QApplication>
#include <QtGui/QButtonGroup>
#include <QtGui/QDialogButtonBox>
#include <QtGui/QHeaderView>
#include <QtGui/QTextEdit>
#include <QtGui/QWidget>
QT_BEGIN_NAMESPACE
class Ui_SweetGuiForm
{
public:
QDialogButtonBox *buttonBox;
QTextEdit *textEdit;
void setupUi(QWidget *SweetGuiForm)
{
if (SweetGuiForm->objectName().isEmpty())
SweetGuiForm->setObjectName(QString::fromUtf8("SweetGuiForm"));
SweetGuiForm->resize(486, 238);
buttonBox = new QDialogButtonBox(SweetGuiForm);
buttonBox->setObjectName(QString::fromUtf8("buttonBox"));
buttonBox->setGeometry(QRect(150, 200, 181, 26));
buttonBox->setStandardButtons(QDialogButtonBox::Cancel|QDialogButtonBox::Ok);
textEdit = new QTextEdit(SweetGuiForm);
textEdit->setObjectName(QString::fromUtf8("textEdit"));
textEdit->setGeometry(QRect(150, 50, 221, 91));
retranslateUi(SweetGuiForm);
QObject::connect(buttonBox, SIGNAL(rejected()), SweetGuiForm, SLOT(close()));
QMetaObject::connectSlotsByName(SweetGuiForm);
} // setupUi
void retranslateUi(QWidget *SweetGuiForm)
{
SweetGuiForm->setWindowTitle(QApplication::translate("SweetGuiForm", "SweetGuiBack", 0, QApplication::UnicodeUTF8));
} // retranslateUi
};
namespace Ui {
class SweetGuiForm: public Ui_SweetGuiForm {};
} // namespace Ui
QT_END_NAMESPACE
#endif // UI_SWEETGUI2_H
Then i recompiled again with my custom slots and shazam! now i can begin to learn some c++.
thanks for all the hints guys, between you all and the documentation i got there.
hope this helps. The main thing to look at is the order things are included i mean my sweetgui2.cpp file
includes the sweetgui2.h file. wich grabs all my custom stuff.
My sweetgui2.h file
includes the ui_sweetgui2.h wich has all the stuff the designer made when i did the first compile. Main.cpp calls my SweetGuiForm class .
As you all can see my first couple days with c++ but this is a good starting point. it made me put the basic flow together in my mind. qt4 assistant look at it.. its well explained and the examples seem very good. ho ho ho merry xmas. hope my explanation helps.

Can't call slot or Q_INVOKABLE from QML in subclass of QQmlPropertyMap

I'm trying to test drive the QQmlPropertyMap class. It seems like it might work well for what I want, if I can subclass it. The documentation here even gives some rudimentary instructions on what to do for subclassing it. Said documentation also indicates that this class derives from QObject.
For what it's worth, I'm using QtCreator 2.6.1 on Qt 5.0.0 with QtQuick 2.0.
My main.qml:
import QtQuick 2.0
Rectangle {
width: 360
height: 360
Text {
text: owner.field
anchors.centerIn: parent
}
MouseArea {
anchors.fill: parent
onClicked: {
owner.testFunc();
}
}
}
My main.cpp:
#include <QtGui/QGuiApplication>
#include "qtquick2applicationviewer.h"
#include "TestMap.h"
#include <QQmlContext>
int main(int argc, char *argv[])
{
TestMap* map = new TestMap();
QGuiApplication app(argc, argv);
QtQuick2ApplicationViewer viewer;
QQmlContext* ctxt = viewer.rootContext();
ctxt->setContextProperty("owner", map);
viewer.setMainQmlFile(QStringLiteral("qml/TestMap/main.qml"));
viewer.showExpanded();
return app.exec();
}
My TestMap.h
#ifndef TESTMAP_H
#define TESTMAP_H
#include <QObject>
#include <QQmlPropertyMap>
#include <QDebug>
class TestMap: public QQmlPropertyMap // QObject
{
Q_OBJECT
public:
TestMap(QObject* parent = 0): QQmlPropertyMap(this, parent) // QObject(parent)
{
insert("field", "value"); // Comment this out
}
TestMap(const TestMap& value) { }
virtual ~TestMap() {}
public slots:
void testFunc()
{
qDebug() << "Success!";
}
};
Q_DECLARE_METATYPE(TestMap)
#endif
When I run, I get a window saying "value", as I'd expect. But when I click on the window, I get a console output saying
TypeError: Property 'testFunc' of object TestMap(0xaaa0b8) is not a function
I've looked for similar problems, but all the search results are about people that forgot to include the Q_OBJECT macro. It must be something I'm doing wrong in the code, because if I make all the changes indicated in the comments of the TestMap file (and leave the main.cpp and main.qml exactly as is), I get the qDebug message I expect.
I'm not sure whether I'm supposed to Q_DECLARE_METATYPE or not (I think the 2-arg protected constructor is supposed to do it for me), but it doesn't work either way.
For the record, the only things I have to change to get it to work are:
1) Derive from QObject instead of QQmlPropertyMap.
2) Change the constructor to:
TestMap(QObject* parent = 0): QObject(parent) {}
And that's it. Since it works when I don't change anything about the main.cpp, main.qml, or the slot itself, I have to conclude it's nothing wrong with those. Can anyone tell me what I'm doing wrong?
This is now fixed in Qt 5.1.0 and onwards. See the following codereview url for details:
https://codereview.qt-project.org/#change,57418

QT C++ - QNetworkAccessManager help needed! Class problem

I'm trying to download a page from a server to my QT program, but I've been searching ways to do it and they don't really work a lot. I'm not an expert in QT/C++, so be kind :)
Well.. So far I come with this code:
[OLD CODE] - Check the updated code bellow!
http.cpp
#include "http.h"
http::http(QObject *parent) :
QObject(parent)
{
qDebug() << "HTTP ST";
http1 = new QHttp(this);
connect(http1, SIGNAL(done(bool)), this, SLOT(httpdown())); // Correction 1.
http1->setHost("localhost");
http1->get("/test.php");
qDebug() << "HTTP END";
}
void http::httpdown()
{
qDebug() << "completed!";
qDebug() << http1->readAll();
}
http.h
#ifndef HTTP_H
#define HTTP_H
#include <QtNetwork>
#include <QHttp>
#include <QDebug>
#include <QObject>
class http : public QObject
{
Q_OBJECT
public:
explicit http(QObject *parent = 0);
signals:
public slots:
void httpdown();
private:
QHttp *http1;
};
#endif // HTTP_H
Well the problem is that httpdown() is never called, and I've tried anything I know :( Probably I'm not doing this correctly.
Help will be much appreciated.
Thanks.
QUESTION UPDATE
I've ear the suggestion of alexisdm and to check QNetworkAccessManager. So here it is new code working on the main() correctly.
When I run it from another class I never get the signal.
[NEW CODE]
http2.cpp
#include "http2.h"
http2::http2(QObject *parent) :
QObject(parent)
{
m_manager = new QNetworkAccessManager(this);
connect(m_manager,SIGNAL(finished(QNetworkReply*)),this,SLOT(httpdown(QNetworkReply*)));
QNetworkRequest request;
request.setUrl(QUrl("http://localhost/test.php"));
request.setRawHeader("User-Agent", "MyOwnBrowser 1.0");
m_manager->get(request);
}
void http2::httpdown(QNetworkReply* result)
{
QByteArray data= result->readAll();
QString str(data);
qDebug() << str;
}
http2.h
#ifndef HTTP2_H
#define HTTP2_H
#include <QObject>
#include <QDebug>
#include <QtNetwork>
#include <QNetworkReply>
class http2 : public QObject
{
Q_OBJECT
public:
explicit http2(QObject *parent = 0);
signals:
public slots:
void httpdown(QNetworkReply* result);
private:
QNetworkAccessManager* m_manager;
};
#endif // HTTP2_H
Now if I call it directly under main.cpp like this:
main.cpp
#include <QtCore/QCoreApplication>
#include "tcpserver.h"
#include "http2.h"
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
http2 h; // --> Working!!
tcpserver mServer;
return a.exec();
}
It works fine. However if I call it inside the tcpserver class like this:
tcpserver.cpp
#include "tcpserver.h"
#include "protocol.h"
#include "http2.h"
QTextStream in(stdin);
tcpserver::tcpserver(QObject *parent) :
QObject(parent)
{
server = new QTcpServer(this);
[ ... Other Server Stuff ... ]
// http2 h; // --> OLD CODE - Not Working :(
http2 *h = new http2(this); // **--> NEW CODE working provided by alexisdm**
}
The signal never happens... What's wrong? I'm new here! :P
Anyway, alexisdm said: "Maybe the http object gets destroyed before the signal can be emitted (if it was allocated on the stack for example)" - Solution accepted, code bellow corrected Read this: QT C++ - QNetworkAccessManager help needed! Class problem (link to answer)
What should I do to avoid that?
Thanks! ;)
Your http or http2 object is destroyed at the end of the constructor, because it is allocated locally.
You should at least allocate it dynamically:
http2 *h = new http2(this);
If you want to reuse it, you can also declare it as a member of tcpserver, instead of using a local variable. If not, you should destroy it somehow when it is not needed anymore.
Edit
If the destruction is done within the slot and/or in response to a signal from h, you should use QObject::deleteLater rather than an immediate delete, because the object might still be referenced somewhere at the time the signal is emitted. So either deleteLater(); in httpdown() or h->deleteLater(); in a tcpserver slot.
To know if you have an answer or an error you could use that code and forward either the data or the error to your tcpserver class with custom signal(s) and slot(s).
The line:
SIGNAL(bool)
really doesn't look right; did you mean
SIGNAL(done(bool))
?
In debug mode, there should be some debug output saying that it could not connect the signals.