Purple Error in Widget Project
-
Hi,
In order to simplify one of my widget projects, I decided to divide my declarations and definitions of my classes and their members for specific sections into various headers and cpp files. Problem is, that now I did that, I get a purple error when I run my code.
This is the error:
@
Object::connect: No such slot Clock_Application::timer_Start() in ./ui_clock_application.h:101
Object::connect: (sender name: 'Start')
Object::connect: (receiver name: 'Clock_Application')
Object::connect: No such slot Clock_Application::timer_Stop() in ./ui_clock_application.h:102
Object::connect: (sender name: 'Pause')
Object::connect: (receiver name: 'Clock_Application')
Object::connect: No such slot Clock_Application::timer_Reset() in ./ui_clock_application.h:103
Object::connect: (sender name: 'Reset')
Object::connect: (receiver name: 'Clock_Application')
@This problem, I realized, was caused by moving my slot declarations outside of the class where I had them in. How would I go about allowing my slots to be declared in other classes besides MainWindow?
-
Slots can be defined in any class which is QObject-based. However, in your connect statement, you have to make sure that the object pointed to is the same type of object that contains your slot.
Without seeing the code changes you've made, it's hard to tell what you're doing.
I think you might be served well by a good review of signals and slots, in general, as it feels like you might not have a full grasp of the operation of them. Have you read "this documentation":/doc/qt-4.8/signalsandslots.html about them?
-
I believe I connected it right. This is my connection:
@
void Stopwatch::timer_Start()
{
stopwatchTimer = new QTimer();
connect(stopwatchTimer, SIGNAL(timeout()), this, SLOT(timer_changeTime()));
stopwatchTimer->start(1000);
}
@This is my class:
@
class Stopwatch : public QObject
{
Q_OBJECT
public:
Stopwatch();
private slots:
void timer_Start();
void timer_Stop();
void timer_Reset();void timer_changeTime();
private:
QTimer* stopwatchTimer;
};
@ -
Looking at the output, you can see that the errors are being generated from ui_clock_application.h, though. Unless your Stopwatch class is defined in ui_clock_application.h, then you're looking in the wrong place.
As an aside, you have a memory leak in your timer_Start() slot. You are creating a new QTimer every time the slot is called. This is bad, because when you create a new one, the old one still exists.
In your Stopwatch constructor, you should have the line:
@
stopwatchTimer = 0; // or NULL
@And then in timer_Start():
@
void Stopwatch::timer_Start()
{
if (!stopwatchTimer) // Only do this stuff if it hasn't been done before.
{
stopwatchTimer = new QTimer();
connect(stopwatchTimer, SIGNAL(timeout()), this, SLOT(timer_changeTime()));
}
stopwatchTimer->start(1000);
}
@(Alternately, you could move the creation and connection of the QTimer into the constructor, and just call stopwatchTimer->start(...) from your slot.)
-
Yeah, the errors are generated in that file, but you cannot save changes to that file.
I will try and fix up that memory leak you mentioned. Thanks.
-
True, you can't save changes to that file, but those items are generated from your .ui file. Make sure that in the .ui file that any signal/slot connections you are making are pointing at the right objects.
-
The arrows are all pointing at the MainWindow (or Clock_Application), so this is what made me wonder whether you can only declare slots in the MainWindow (or Clock_Application) class.
-
There's nothing magical about MainWindow or Clock_Application or anything like that. There's just a connection being made somewhere (looks like in your .ui file) which is still expecting the timer_Start() slot (etc.) to be in the old location. Just moving the slot definition isn't enough to make the .ui file look point to the right place.
What are you doing in the clock_application.ui file which calls timer_Start()? What triggers timer_Start() to be called?
-
timer_Start() is triggered by a click of a button in the widget application. The button is a simple QPushButton.
-
Where is the connection made?
-
When you say "connection" do you refer to my connect() function? If so, here it is:
@
void Stopwatch::timer_Start()
{
stopwatchTimer = new QTimer();
connect(stopwatchTimer, SIGNAL(timeout()), this, SLOT(timer_changeTime()));
stopwatchTimer->start(1000);
}
@ -
No. What makes the button call timer_Start(). How do you tell it to do this?
-
I use that one menu in Qt Designer that allows you to draw blue/red arrows. I then create a new slot, and call it "timer_Start()", and I believe, this automatically connects the clicked() signal and the timer_Start() slot.
-
The arrows need to point to Stopwatch, not Clock_Application, if the slots are defined in Stopwatch.
Behind the scenes, those arrows translate to a "connect()" call in the ui_clock_application.h file.
-
How do I get it to "point" to Stopwatch? Stopwatch is just a class. It does not really refer to any widget.
-
Ah. Good point. In that case, I'd say that there shouldn't be any arrows anywhere, and that you should make the connection in code.
Edit to add:
Alternately, you could keep "proxy" slots in your Clock_Application widget, and from within those slots just call the slots in Stopwatch.
That is to say:
@
class Clock_Application ...
{
Q_OBJECT
...
public slots:
void timer_Start() { m_stopwatch->timer_Start(); } // just "pass through" to your Stopwatch class. (Remember that slots are just plain old methods too, and can be directly called like any other method.)
...
private:
Stopwatch *m_stopwatch;
};
@ -
Hmm.. now I am receiving a strange error:
multiple definition of
ui
first defined here
collect2: Id returned 1 exit statusThe lines in where the errors occur do not seem to be in my project, but in other files.. possibly library files? It's also strange, because I have defined my own
ui
just previously, and am wondering what is causing it now.