I have declared QOBJECT macro but still its calling the function without passing the QObject object
Here is my code
keyusermanagertest.cpp
#define private public
#define protected public
#include "keyusermanagertest.h"
#include "storageusermanager.h"
#include "keyusermanager.h"
#include "alkuser.h"
#undef protected
#undef private
#include <QDebug>
#include <QtTest/QtTest>
QTEST_MAIN(KeyUserManagerTest)
void KeyUserManagerTest::init()
{
}
void KeyUserManagerTest::cleanup()
{
}
void KeyUserManagerTest::test_initialization()
{
// Already tested under BackendTest::test_initialization()
}
void KeyUserManagerTest::settersAndGetters()
{
AlkUser userInfo;
QString user="Puneet Goyal";
StorageUserManager* storageuser=new StorageUserManager();
KeyUserManager* keyuser=new KeyUserManager(storageuser);
keyuser->updateUserData(user,userInfo);
qDebug()<<"UPDATION DONE!!!!";
// Now setting the rest of the details for user Puneet Goyal using AlkUser Object
userInfo.setName("Puneet");
userInfo.setContact("21897121");
userInfo.setType("savings");
userInfo.setAccount("123456789");
userInfo.setAmount("100000");
// Now retrieving all the user details using KeyUserManager Object
QVariant vari=keyuser->getUserInfo("Puneet Goyal");
}
keyusermanagertest.h
#ifndef KEYUSERMANAGERTEST_H
#define KEYUSERMANAGERTEST_H
#include <QtCore/QObject>
class KeyUserManager;
class KeyUserManagerTest : public QObject
{
Q_OBJECT
private slots:
void init();
void cleanup();
void test_initialization();
void settersAndGetters();
};
#endif
Its compile output is as follows"
/home/puneet/puneet/office/alkimia/payment/backend/keyusermanagertest.cpp: In member function ‘void KeyUserManagerTest::settersAndGetters()’:
/home/puneet/puneet/office/alkimia/payment/backend/keyusermanagertest.cpp:52: error: no matching function for call to ‘StorageUserManager::StorageUserManager()’
/home/puneet/puneet/office/alkimia/payment/backend/storageusermanager.h:41: note: candidates are: StorageUserManager::StorageUserManager(QObject*)
/home/puneet/puneet/office/alkimia/payment/backend/storageusermanager.h:37: note: StorageUserManager::StorageUserManager(const StorageUserManager&)
/home/puneet/puneet/office/alkimia/payment/backend/keyusermanagertest.cpp:53: error: no matching function for call to ‘KeyUserManager::KeyUserManager(StorageUserManager*&)’
/home/puneet/puneet/office/alkimia/payment/backend/keyusermanager.h:44: note: candidates are: KeyUserManager::KeyUserManager(StorageUserManager*, QObject*)
/home/puneet/puneet/office/alkimia/payment/backend/keyusermanager.h:41: note: KeyUserManager::KeyUserManager(const KeyUserManager&)
Thanks
Add constructor to your KeyUserManagerTest -
in header add
KeyUserManagerTest (QObject* parent=0);
and in cpp
KeyUserManagerTest::KeyUserManagerTest(QObject* parent):QObject(parent){};
QOBJECT macro does not create constructor for you!
Related
Started using QtRO and generated files inherently complain about vtable:
#ifndef REP_REMOTEEXAMPLE_H
#define REP_REMOTEEXAMPLE_H
// This is an autogenerated file.
// Do not edit this file, any changes made will be lost the next time it is generated.
#include <QtCore/qobject.h>
#include <QtCore/qdatastream.h>
#include <QtCore/qvariant.h>
#include <QtCore/qmetatype.h>
#include <QtRemoteObjects/qremoteobjectnode.h>
#include <QtRemoteObjects/qremoteobjectpendingcall.h>
#include <QtRemoteObjects/qremoteobjectreplica.h>
class remoteExampleReplica : public QRemoteObjectReplica
{
Q_OBJECT
Q_CLASSINFO(QCLASSINFO_REMOTEOBJECT_TYPE, "remoteExample")
Q_CLASSINFO(QCLASSINFO_REMOTEOBJECT_SIGNATURE, "5e40a606abdd95f709878d419edaa735fce25d0d")
public:
remoteExampleReplica() : QRemoteObjectReplica() { initialize(); }
static void registerMetatypes()
{
static bool initialized = false;
if (initialized)
return;
initialized = true;
}
private:
remoteExampleReplica(QRemoteObjectNode *node, const QString &name = QString())
: QRemoteObjectReplica(ConstructWithNode)
{
initializeNode(node, name);
}
void initialize() override
{
remoteExampleReplica::registerMetatypes();
QVariantList properties;
properties.reserve(0);
setProperties(properties);
}
public:
virtual ~remoteExampleReplica() {}
Q_SIGNALS:
void Close(QString a);
void Open(QString b);
public Q_SLOTS:
void onClosed()
{
static int __repc_index = remoteExampleReplica::staticMetaObject.indexOfSlot("onClosed()");
QVariantList __repc_args;
send(QMetaObject::InvokeMetaMethod, __repc_index, __repc_args);
}
void onOpened()
{
static int __repc_index = remoteExampleReplica::staticMetaObject.indexOfSlot("onOpened()");
QVariantList __repc_args;
send(QMetaObject::InvokeMetaMethod, __repc_index, __repc_args);
}
private:
friend class QT_PREPEND_NAMESPACE(QRemoteObjectNode);
};
#if (QT_VERSION < QT_VERSION_CHECK(5, 5, 0))
#endif
QT_BEGIN_NAMESPACE
QT_END_NAMESPACE
#endif // REP_REMOTEEXAMPLE_H
The issue points to the private constructor. I only included the replica header in my code without really using the remote object as a test run. I've read a lot about vtables how they work and when the linker complains about the vtable but in this case, with the private constructor, I'm not sure what the issue is. Am I missing an implementation of the remote object? Did I not generate the files correctly?
.rep:
class remoteExample
{
SIGNAL(Close(QString a));
SIGNAL(Open(QString b));
SLOT(onClosed());
SLOT(onOpened());
};
I have a qt thread in my application which emits a Mat type image so that other threads can use it. the image is coming from camera by using VideoCapture Object of opencv library. now what i intend to do is getting this image from a rostopic, not from camera directly. in order to do that i must create a ros node in my thread and here i am stuck. is there anyone who has the experience to integrate ros node and qt?
here is my thread:
#include "../include/Ground_Station/camera.h"
#include <iostream>
using namespace std;
Camera::Camera()
{
}
void Camera::run()
{
VideoCapture cap;
cap.open(0);
while(1){
Mat image;
cap >> image;
cvtColor(image,image,CV_BGR2RGB);
emit ImgSignal(&image);
QThread::msleep(30);
}
}
and Camera.h:
#ifndef CAMERA_H
#define CAMERA_H
#include <QObject>
#include <QThread>
#include <QtCore>
#include <QtGui>
#include <image_transport/image_transport.h>
#include <cv_bridge/cv_bridge.h>
#include <ros/ros.h>
#include <opencv2/opencv.hpp>
using namespace cv;
class Camera: public QThread
{
Q_OBJECT
public:
Camera();
void run();
bool Stop = false;
signals:
void ImgSignal(Mat*);
private:
public slots:
};
#endif // THREAD_H
Basically, your executable file containing the main() function must be your ros node and your QT application at the same time. In your "main.cpp"
you call ros::init(...) and subscribe to the topic you want to listen to. Your subscriber callback function may convert the ros image to Mat and emmit an ImgSignal every time it is called. To do all that, I'd create a RosImageProvider class, something along the lines ..
class RosImageProvider: public QObject
{
Q_OBJECT
public:
void ImageSubscriberCallback(const sensor_msgs::Image::ConstPtr& img);
...
signals:
void ImgSignal(Mat*);
};
I encountred the same problem when dealing with TCP/IP connection from a ROS node within Qt and my solution was to inherit directly from the QThread object, thus when initializing the class, you initialize the ROS node and implement the work TODO in callbacks and the thread run() function.
So finally, my code looked something like this :
#ifndef INCLUDE_TCPHANDLER_HPP_
#define INCLUDE_TCPHANDLER_HPP_
#include <ros/ros.h>
#include <QThread>
#include <string>
class TCP_Handler : public QThread
{
Q_OBJECT
private:
int init_argc;
char** init_argv;
ros::Publisher cmd_control_publisher;
ros::Subscriber feedback_subscriber;
public:
TCP_Handler()
{}
virtual ~TCP_Handler(){}
/**
* #brief ROS methods
*
*/
inline bool init_ros()
{
int argc =0; char** argv = new char*();
ros::init(argc,argv,"tcp_handler");
ros::NodeHandle n;
cmd_control_publisher = n.advertise<robot_common::cmd_control>("cmd_control", 1000);
feedback_subscriber = n.subscribe<robot_common::feedback>("wifibot_pose", 4, &TCP_Handler::FeedbackCallback , this);
return true;
}
void FeedbackCallback(const robot_common::feedback::ConstPtr& pose)
{
//.....
}
/**
* #brief Threading methods
*
*/
virtual void init(int, std::string ip_addr = "127.0.0.1") = 0;
virtual void run() = 0;
virtual void stop() = 0;
/**
* #brief TCP methods (Server/Client have to implement these folks)
*
*/
virtual bool Send_data(char* data, int size) = 0;
virtual int Receive_data(char* in_data, int size) = 0;
virtual bool Open_connection() = 0;
virtual void Close_connection() = 0;
};
#endif /* INCLUDE_TCPHANDLER_HPP_ */
This code is just a template of a Qt-threaded-ROS node for TCP connction as I don't know your specific needs. feel free to build your own !
Cheers,
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.
I am trying to use a method called getName() that is defined in the addPlayer.h file below. The getname() method will be used in the constructor called Player. The error that I get is: 'getName' was not declared in this scope'. How can I fix it?
Thanks for helping.
The addPlayer.h file:
#include "../Source/Player.h"
class addPlayer : public QDialog
{
Q_OBJECT
public:
addPlayer(QWidget *parent = 0);
~addPlayer();
tp::Player* makePlayer();
void addPlayer();
QString getName() const;
inline QString addPlayer::getName() const
{
return (ui.name_lineEdit->text());
}
The addPlayer.cpp file:
#include "addPlayer.h"
#include <QMessageBox>
using namespace tp;
addPlayer::addPlayer(QWidget *parent)
: QDialog(parent)
{
ui.setupUi(this);
QObject::connect(ui.ok_pushButton, SIGNAL(clicked()), this,
SLOT(validatePlayer()));
QObject::connect(ui.dateNaissance_pushButton, SIGNAL(clicked()), this,
SLOT(getDate()));
}
addPlayer::~addPlayer()
{
}
Player* makePlayer()
{
return new Player(getName().toStdString());
}
The constructor is as follows:
class Player: public HumanBeing {
public:
//Constructor
Player(const std::string& p_name);
Player::Player(const std::string& p_name): m_name(p_name)
You haven't properly scoped your definition of makePlayer -- you need to prefix addPlayer:::
Player* addPlayer::makePlayer()
{
return new Player(getName().toStdString());
}
I have something like that:
Prueba.h
#include <QObject>
class Prueba:public QObject
{
Q_OBJECT
private:
bool waiting;
public:
Prueba();
void test();
void fin();
signals:
void comenzo();
};
Prueba.cpp
#include "prueba.h"
#include <QDebug>
Prueba::Prueba()
{
waiting=true;
}
void Prueba::test()
{
qDebug()<<"Comenzando";
emit(comenzo());
while(waiting) {
qDebug()<<"Esperando";
}
qDebug()<<"Termino";
}
void Prueba::fin()
{
waiting=false;
}
Principal.h
#include <QObject>
#include "prueba.h"
class Principal:public QObject
{
Q_OBJECT
private:
Prueba * prueba;
public:
Principal();
private slots:
void processSignal();
};
Principal.cpp
#include <QDebug>
Principal::Principal()
{
prueba=new Prueba();
connect(prueba,SIGNAL(comenzo()),SLOT(processSignal()));
prueba->test();
}
void Principal::processSignal()
{
for(int i=0;i<1000;i++) {
qDebug()<<"Algo";
}
prueba->fin();
}
When I call prueba->test(), and it emit the signal "comenzo", Principal::proccessSignal is completely executed, and never enters to the cycle "while(waiting)". What I need to do for that the code inside the loop is executed?
My guess is your signal connection. By default Qt will execute your signal as a direct call to the slot the objects are in the same thread as you can see here:
QMetaObject::Connection QObject::connect(
const QObject * sender, const char * signal,
const char * method, Qt::ConnectionType type = Qt::AutoConnection) const
See Qt::ConnectionType here http://qt-project.org/doc/qt-5.0/qtcore/qt.html#ConnectionType-enum
So if you use
Qt::QueuedConnection
in your signal connection
connect(prueba,SIGNAL(comenzo()),SLOT(processSignal()), Qt::QueuedConnection);
It should work as expected. See
The slot is invoked when control returns to the event loop of the receiver's thread. The slot is executed in the receiver's thread.