QT signals and slots unexpected Error - qt

This is driving me insane....it was working earlier, but not it doesn't work. I have defined Q_SLOTS and Q_SIGNALS, and I was trying to connect them. It was working to an extent...and then all of a sudden everything stopped working, and now I am getting errors. My code is the following:
ControllerLogic.h
#ifndef CONTROLLERLOGIC_H
#define CONTROLLERLOGIC_H
#include "initdataaccess.h"
#include "mainframe.h"
#include <QtGui>
#include "initializationdatastructure.h"
/** This is a controller class; refering to the model-view-controller
* architecture.
*/
class ControllerLogic : public QObject
{
Q_OBJECT
public:
ControllerLogic(InitDataAccess *initDataAccess, MainFrame *mainFrame);
Q_SIGNALS:
void Signal();
private:
void setMainFrame(MainFrame mainFrame);
public Q_SLOTS:
void receive();
};
#endif // CONTROLLERLOGIC_H
ControllerLogic.cpp
#include "controllerlogic.h"
#include "licensedataaccess.h"
#include <qobjectdefs.h>
// obsolete...may be used later
ControllerLogic::ControllerLogic(InitDataAccess *initDataAccess, MainFrame *mainFrame)
{
connect(this, SIGNAL(signal()), mainFrame, SLOT(PrintTestSlot()));
}
void ControllerLogic::receive(){
qDebug()<<"RECEIVE";
}
void ControllerLogic::Signal(){
qDebug()<<"SIGNAL";
}
ERROR
moc_controllerlogic.obj:-1: error: LNK2005: "protected: void __thiscall ControllerLogic::Signal(void)" (?Signal#ControllerLogic##IAEXXZ) already defined in controllerlogic.obj
release\TSLSuite.exe:-1: error: LNK1169: one or more multiply defined symbols found
I also tried to define the signal as follows:
public:
Q_SIGNAL void Signal();
but I get the same error.
What is going on?
Please Help!
Thanks!

The problem is that you're trying to define a function called Signal()
Qt generates the body of the "signal" functions for you, and if you try to create your own definition, you will get the error that you're describing.
(As a side note, your connect statement appears to be broken s/signal/Signal/)

Related

When is it mandatory to call qRegisterMetaType()?

I have studied the qt documentation of qRegisterMetaType() where it says that this function must be called before the corresponding type can be used in signal/slot mechanism. However I couldn't find any code example where this has to be done by hand.
This page states, that the registration is done automatically by the moc if it can determine that the type may be registered as meta-type. It looks like this is right, because I tested QSignalSpy, QObject::connect() (direct and queued connection) and QVariant - with just using Q_DECLARE_METATYPE(type) and none of them needed a explicit call to qRegisterMetaType to work.
So my question is: when do I have to call qRegisterMetaType(), because otherwise the code won't work?
The Qt docs say that Q_DECLARE_METATYPE is necessary in case one has a connect being a queued connection.
Adding a Q_DECLARE_METATYPE() makes the type known to all template
based functions, including QVariant. Note that if you intend to use
the type in queued signal and slot connections or in QObject's
property system, you also have to call qRegisterMetaType() since the
names are resolved at runtime.
For this I build a small testing app, that exemplifies the behavior.
Just try to remove the Q_DECLARE_METATYPE(Message) and watch the warnings and output change. In case of the normal connect the macro seems to be unnecessary.
main.cpp
#include <QApplication>
#include <QThread>
#include "MyHeaderView.h"
Q_DECLARE_METATYPE(Message);
int main(int argc, char **args)
{
QApplication app(argc, args);
{
TestObject sender;
TestObject receiver;
QObject::connect(&sender, &TestObject::sendMessage, &receiver, &TestObject::onMessage);
sender.emitMessage(1, 2);
}
// This requires Q_DECLARE_METATYPE(Message);
QThread workerThread;
TestObject sender2;
TestObject receiver2;
receiver2.moveToThread(&workerThread);
workerThread.start();
QObject::connect(&sender2, &TestObject::sendMessage, &receiver2, &TestObject::onMessage, Qt::ConnectionType::QueuedConnection);
sender2.emitMessage(3, 4);
app.exec();
}
TestObject.h
#pragma once
#include <QObject>
#include <QDebug>
struct Message
{
int x;
int y;
};
class TestObject : public QObject
{
Q_OBJECT
public:
void emitMessage(int x, int y) { emit sendMessage(Message{ x,y }); }
signals:
void sendMessage(const Message&);
public slots:
void onMessage(const Message& m) { qDebug() << m.x << m.y; }
};

QTextBrowser for Helper

I am trying to make a helper with QTextBrowser. As I understood, home(), backward() and forward() are already implemented in QTextBrowser and required only connections to the buttons. Below there is .h and .cpp files
#ifndef HELPWINDOW_H
#define HELPWINDOW_H
#include <QDialog>
namespace Ui {
class HelpWindow;
}
class HelpWindow : public QDialog
{
Q_OBJECT
public:
explicit HelpWindow(QWidget *parent = 0);
~HelpWindow();
private slots:
private:
Ui::HelpWindow *ui;
};
#endif // HELPWINDOW_H
and
#include "helpwindow.h"
#include "ui_helpwindow.h"
HelpWindow::HelpWindow(QWidget *parent) :
QDialog(parent),
ui(new Ui::HelpWindow)
{
ui->setupUi(this);
// connection
connect(ui->pushButton_home,SIGNAL(clicked()),ui->textBrowser,SLOT(home()));
connect(ui->pushButton_forward,SIGNAL(clicked()),ui->textBrowser,SLOT(forward()));
connect(ui->pushButton_backward,SIGNAL(clicked()),ui->textBrowser,SLOT(backward()));
}
HelpWindow::~HelpWindow()
{
delete ui;
}
There is no any error message. It is possible to read and click the links inside QTextBrowser. Only there are no any actions with buttons. What do I miss here?
You need to call either one or both of the following properties
ui->textBrowser.setOpenLinks(true);
ui->textBrowser.setOpenExternalLinks(true);
and if you want filter or re-route the links at runtime
connect(ui->textBrowser, SIGNAL(sourceChanged(QUrl)), pointerToYourCode, SLOT(slotSourceChanged(QUrl)));
and implement
void YourCode::slotSourceChanged(const QUrl& url) {...}
I found why it did not work. The initial source should be specify:
ui->textBrowser->setSource(QUrl::fromLocalFile("help/index.html"));
Thank you, Jens for spending time.

Connection of pure virtual signal of interface class

I want to connect some object's signals derived from an interface class.
The connection is done in QWidget::listenToAnimal(AnimalInterface*).
This does not work because qt_metacall is not a member of 'AnimalInterface' and static assertion failed: No Q_OBJECT in the class with the signal.
Of course AnimalInterface does not have the Q_OBJECT macro and does not inherit QObject because it is an interface...
I want to connect through the interface class because I do not want to manually retype the same code for Cat and for Dog.
Is it possible to connect the signal the way I want to? Perhaps with templates? Is this perhaps a lambda-specific problem?
header:
#ifndef WIDGET_H
#define WIDGET_H
#include <QWidget>
class AnimalInterface{
public:
virtual ~AnimalInterface();
virtual void makeSound() = 0;
/*signals*/
virtual void madeSound() = 0;
};
Q_DECLARE_INTERFACE(AnimalInterface,"interface")
class Dog : public QObject, public AnimalInterface
{
Q_OBJECT
Q_INTERFACES(AnimalInterface)
public:
void makeSound();
signals:
void madeSound();
};
class Cat : public QObject, public AnimalInterface
{
Q_OBJECT
Q_INTERFACES(AnimalInterface)
public:
void makeSound();
signals:
void madeSound();
};
class Widget : public QWidget
{
Q_OBJECT
Cat *cat_;
Dog *dog_;
public:
Widget(QWidget *parent = 0);
~Widget();
void listenToAnimal(AnimalInterface *animal);
};
#endif // WIDGET_H
cpp:
#include "widget.h"
#include <QDebug>
Widget::Widget(QWidget *parent)
: QWidget(parent)
{
dog_ = new Dog;
cat_ = new Cat;
listenToAnimal(dog_);
listenToAnimal(cat_);
dog_->makeSound();
cat_->makeSound();
}
void Widget::listenToAnimal(AnimalInterface *animal)
{
connect(animal, &AnimalInterface::madeSound,
this,
[](){
qDebug()<<"animal made sound";
});
}
Widget::~Widget()
{
}
void Cat::makeSound()
{
qDebug()<<"Cat says miaow";
emit madeSound();
}
void Dog::makeSound()
{
qDebug()<<"Dog says wuff";
emit madeSound();
}
main.cpp
#include "widget.h"
#include <QApplication>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
Widget w;
w.show();
return a.exec();
}
Since you know the derived type at compile type, you can connect to the proper, statically-known QObject-derived type. No need for dynamic casting or anything of the sort. You just don't want the listenToAnimal method to be available for non-AnimalInterface-inheriting types, though, even if it they have a compatible madeSound method:
C++11
#include <type_traits>
template< class T,
typename =
typename std::enable_if<std::is_base_of<AnimalInterface, T>::value>::type >
void listenToAnimal(T * animal) {
connect(animal, &T::madeSound, this, []{ qDebug() << "animal made sound"; });
}
C++03
template <class T>
void listenToAnimal(T * animal) {
Q_UNUSED(static_cast<AnimalInterface*>(animal));
connect(animal, &T::madeSound, this, &Widget::onAnimalMadeSound);
}
You can then use it without having to spell out the type - it's already known to the compiler:
listenToAnimal(dog_);
listenToAnimal(cat_);
If the derived type is not known at compile time, you have to dynamically cast to QObject and connect by name, not by method pointer. It will assert at runtime if you've passed in a wrong type - after all, it's not enough for it to be an instance of AnimalInterface, it also needs to be a QObject instance.
void listenToAnimal(AnimalInterface * animal) {
auto object = dynamic_cast<QObject*>(animal);
Q_ASSERT(object);
connect(object, SIGNAL(madeSound()), this, SLOT(onAnimalMadeSound()));
}
The fact that the type AnimalInterface has a virtual madeSound method is somewhat relevant - it guarantees that the derived class implements the method with such a signature. It doesn't guarantee that the method is a signal, though. So you should probably rethink your design and ask yourself: "What do I gain by using a static type system when I can't really use it for static type checking"?
Most likely you should make any methods that would nominally accept the AnimalInterface*, be parametrized and take a pointer to the concrete class. Modern code generators and linkers will deduplicate such code if type erasure leads to identical machine code.
Found a solution with templates. Did not work the first time I tried, obviously did something wrong first. Here it goes...
Just replace the corresponding parts from the example in the question (and remove definition of listenToAnimal from the source file):
header:
template<class T>
void listenToAnimal(AnimalInterface *animal)
{
T *animal_derivate = dynamic_cast<T*>(animal);
if (animal_derivate){
connect(animal_derivate, &T::madeSound,
this,
[](){
qDebug()<<"animal made sound";
});
}
}
cpp:
listenToAnimal<Dog>(dog_);
listenToAnimal<Cat>(cat_);
Update:
After trying Kuba Ober's answer, it seems like this is working best now:
template<typename T>
typename std::enable_if<std::is_base_of<AnimalInterface, T>::value,void>::type
listenToAnimal(T *animal)
{
connect(animal, &T::madeSound, this, [](){ qDebug()<<"animal made sound"; });
}
However, the one point still not working is how to connect if I create an animal like AnimalInterface *bird = new Bird, because it throws the same error that the base class does not have the signal.

Qt subclassing from QWidget

I write my own class which subclass from QWidget
And this is my header file
#ifndef GRAPHMATRIX_H
#define GRAPHMATRIX_H
#include "treemodel.h"
#include <QWidget>
#include <Qt/qtableview.h>
class GraphMatrix : public QWidget
{
Q_OBJECT
public:
TreeModel& getModel();
GraphMatrix(QWidget* parent = 0);
void addTop(QString name);
void cutComponent(GraphMatrix* component, QVector<int> columns);
private:
TreeModel model;
QTableView* view;
public slots:
void changeValue(const QModelIndex& index);
};
#endif // GRAPHMATRIX_H
And I am getting this error
error C2248: 'QWidget::QWidget' : cannot access private member declared in class 'QWidget'
Can anyone help me?
Updated to add: I find answer, problem is in QList I must write QList. because QList is using copy constructor. Thank you for giving time for my problem
It looks like you are trying to call the default constructor of QWidget which is private. Instead, your constructor needs to call the public constructor of QWidget as follows:
GraphMatrix::GraphMatrix(QWidget* parent) : QWidget(parent) {}
I find answer, problem is in QList I must write QList. because QList is using copy constructor. Thank you for giving time for my problem

Qt: Trying to do a httprequest, but does not seem to work. What is wrong?

I've been using this example to create a http request for my Qt Nokia application, but I can't seem to get it working.
At first I Tried QHttp, but it is deprecated.
Here's the structure:
mainwindow.cpp
mainwindow.h
request.cpp
request.h
Here's the code:
mainwindow.cpp
MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWindow)
{
ui->setupUi(this);
Request* request = new Request();
}
MainWindow::~MainWindow()
{
delete ui;
}
Request.h
#ifndef REQUEST_H
#define REQUEST_H
#include <QNetworkAccessManager>
#include <QUrl>
#include <QNetworkReply>
#include <QNetworkRequest>
class Request : QObject
{
//Q_OBJECT
public:
Request();
public slots:
void finishedSlot(QNetworkReply* reply);
void checkConnection(QNetworkReply* reply);
};
#endif // REQUEST_H
And btw... what use is the "Q_OBJECT" for?
Request.cpp
#include "request.h"
#include <QDebug>
#include <QMessageBox>
Request::Request()
{
QNetworkAccessManager* oNetworkAccessManager = new QNetworkAccessManager(this);
QObject::connect(oNetworkAccessManager, SIGNAL(finished(QNetworkReply*)),this,SLOT(finishedSlot(QNetworkReply*)));
QObject::connect(oNetworkAccessManager, SIGNAL(networkSessionConnected()),this,SLOT(checkConnection(QNetworkReply*)));
QUrl url("http://www.redrock.no");
QNetworkReply* reply = oNetworkAccessManager->get(QNetworkRequest(url));
}
void Request::checkConnection(QNetworkReply* reply)
{
QMessageBox msgBox;
msgBox.setText("checkConnection");
msgBox.setInformativeText("The network session has started");
msgBox.setStandardButtons(QMessageBox::Save | QMessageBox::Discard | QMessageBox::Cancel);
msgBox.setDefaultButton(QMessageBox::Save);
int ret = msgBox.exec();
}
void Request::finishedSlot(QNetworkReply* reply)
{
QMessageBox msgBox;
msgBox.setText("checkConnection");
msgBox.setInformativeText("The request is done");
msgBox.setStandardButtons(QMessageBox::Save | QMessageBox::Discard | QMessageBox::Cancel);
msgBox.setDefaultButton(QMessageBox::Save);
int ret = msgBox.exec();
}
The message boxes is just since I don't have a usb cable for my phone.
I have set breakpoints at both the "checkConnection" slot and the "finishedSlot" slot, but nothing happens there.
Anyone got an idea of what I could be doing wrong?
Here is an explanation of the Q_OBJECT macro:
http://doc.qt.nokia.com/latest/qobject.html#Q_OBJECT
Among other things,
The Q_OBJECT macro must appear in the
private section of a class definition
that declares its own signals and
slots...
So I would first try uncommenting that and see what changes. It should at least get your signals and slots talking to one another. (This is a Qt-specific feature, not part of C++, and needs the Q_OBJECT macro.) I didn't look carefully at the rest of your code, because that is the obvious first thing to try. Actually, I am surprised that it would even compile without that.
ok, finally i found what's wrong... and as usual, it's just a minor error from me.
I uncommented the Q_OBJECT, and got some vtable error or something like that. I did get this error message earlier today when i had the Q_OBJECT there, and that is why i commenting it.
But since i'm new to Qt i hade forgot to incelude the QObject in the request.h
"#include "
And that fixed everything for me :)
Thanks for the explenation and elaboration Dave.

Resources