PDA

View Full Version : Qt signal error : undefined reference to 'FramesEditor::setNewActiveFrame(Frame *)' ?



keshav2010
1st March 2018, 10:00
I'm making a simple animation software, cutting it short, basically, i have made few classes out of which
FrameManager class manages animation frames (inside a QMap<int, Frame*> )
FramesEditor class inherits QGraphicsView and is used to view current active frame ( QGraphicsScene)

These classes are all implemented using singleton design pattern, however, im facing issue when defining connection only between FrameManager and FramesEditor instances

in FrameManager class


void FrameManager::setCurrentActiveFrame(int frameID)
{
qDebug()<<">>> frameManager.cpp : currentActiveFrame ID : "<<currentActiveFrame;
Frame *activeFrame = frameBank[keyStartFrame];

if(frameBank.contains(frameID)){
currentActiveFrame = frameID;
activeFrame = frameBank[currentActiveFrame];
}
qDebug()<<">>> frameManager.cpp : currentActiveFrame ID updated: "<<currentActiveFrame;

emit (FramesEditor::getInstance())->setNewActiveFrame(activeFrame); //causing error
}


the last line where im emitting the signal, it is causing the issue

E:\GITHUB_REPOSITORIES\ProtoAnimator\protoanimator \framemanager.cpp:74: error: undefined reference to `FramesEditor::setNewActiveFrame(Frame*)'

I've checked everything such as including frameseditor.h header and related files but could not figure out why is this happening

in case you need more code, here is how im defining connections

I have 3 classes (singleton)
1. Manager (this class is acting as a communication handler between other 2 manager classes)
2. FrameManager
3. SpriteManager

the manager class is acting as a central class that is initialized first
inside it's constructor, i have one of the connection


connect(FramesEditor::getInstance(), SIGNAL(setNewActiveFrame(Frame*)), FramesEditor::getInstance(), SLOT(renderFrame(Frame*)));


note that renderFrame(Frame*) simply calls setScene() method

high_flyer
1st March 2018, 10:55
I don't have the time to look at the emit implmentation, but I don't think emit can do what your code is telling it.
As far as I know, emit needs a signature of an empty method defined as a signal (that moc then translates to calls in an meta object).

One why to do it is to wrap the signal emitting in your singleton:
Something like this:


void FramesEditor::emitSetNewActiveFrame(Frame *frame){
emit setNewActiveFrame(frame);
}


and in the using code:



void FrameManager::setCurrentActiveFrame(int frameID)
{
qDebug()<<">>> frameManager.cpp : currentActiveFrame ID : "<<currentActiveFrame;
Frame *activeFrame = frameBank[keyStartFrame];

if(frameBank.contains(frameID)){
currentActiveFrame = frameID;
activeFrame = frameBank[currentActiveFrame];
}
qDebug()<<">>> frameManager.cpp : currentActiveFrame ID updated: "<<currentActiveFrame;

//emit (FramesEditor::getInstance())->setNewActiveFrame(activeFrame); //causing error
FramesEditor::getInstance()->emitSetNewActiveFrame(activeFrame);
}


You will also need to update your connect().
But there is also a deisgn issue here.
You are emitting a signal defined in FramesEditor from FrameManager, which is possible as I have shown but points to a design flaw.
Since signals are only messages, they should be defined by the signaling object.
So I don't see why this signal is defined in FramesEditor and not in FrameManager.
That is probably the best line of action - move the signal to FrameManager since it is the class actually emitting the signal.

keshav2010
1st March 2018, 12:01
Thanks for pointing out the design flaw, and also updated connect to a newer syntax. That fixed the issue :)