PDA

View Full Version : No Such Slot



k3ro
20th February 2016, 20:51
I have a dialog window with a slider. I'm trying to make it so that a QLabel will change as the slider changes, but I'm having problems with the slot.

The error message is:


QMetaObject::connectSlotsByName: No matching signal for on_sizeslider_valuechanged(int)
QObject::connect: No such slot Dialog:: on_sizeslider_valuechanged(int value) in ..\GUINew\dialog.cpp:104
QObject::connect: (receiver name: 'Dialog')


My project is quite long, I will post the whole header file but only the relevant part of the .cpp file.

Dialog.h


#ifndef DIALOG_H
#define DIALOG_H

#include <QDialog>
#include <QGridLayout>
#include <QHBoxLayout>
#include <QLabel>

namespace Ui {
class Dialog;
}

class Dialog : public QDialog
{
Q_OBJECT
QGridLayout *gridlayout;
QHBoxLayout *usernamelayout;
QHBoxLayout *sizelayout;
QHBoxLayout *skilllayout;
QHBoxLayout *texlayout;

QLabel *sizechoice;

public:
explicit Dialog(QWidget *parent = 0);
~Dialog();

public slots:
void on_sizeslider_valuechanged(int value);

private:
Ui::Dialog *ui;
};

#endif // DIALOG_H



Dialog.cpp


QObject::connect(sizeslider, SIGNAL(valueChanged(int)), this, SLOT(on_sizeslider_valuechanged(int value)));

}

void Dialog::on_sizeslider_valuechanged(int value){

if (value == 1) {
Dialog::sizechoice->setText("Small");
}
if (value == 2) {
Dialog::sizechoice->setText("Medium");
}
if (value == 3) {
Dialog::sizechoice->setText("Large");
}
if (value == 4) {
Dialog::sizechoice->setText("XLarge");
}

}


I've tried clean/rebuild/qmake.

I'm not sure what's wrong with it. The function is clearly there, and it's defined under 'public slots' in the header, but the program seems to think Dialog doesn't have a slot of that name.

Any help would be appreciated.

ars
20th February 2016, 23:10
Hello,

the signal from your sizeslider has the name "valueChanged(int)". Using the connection by name
void on_sizeslider_valuechanged(int value); Qt tries to connect the slot on_sizeslider_valuechanged(int) to a signal valuechanged(int) of sizeslider. The slider signal is valueChanged(int) (capital C), so no connection can be established. If you want to go with connection by name you should change your slot name to on_sizeslider_valueChanged(int).

Applying this change will run you into the next issue triggered by the (changed) line

QObject::connect(sizeslider, SIGNAL(valueChanged(int)), this, SLOT(on_sizeslider_valueChanged(int)));
Note the 2 changes in this line. First using on_sizeslider_valueChanged with capital C and second removing the argument name value from its parameter list. With this change your slot on_sizeslider_valueChanged(int) will be called twice for every change of the slider: one call for the connection by name and the other one for your explicit connection. So you should decide for a method of connection: In case of connecting by name remove your explicit connect statement. If you prefer explicit connection, rename your slot to something that is not recognized by Qt for connecting by name, e.g. sizesliderValueChanged(int).

Personally I dislike the connection by name and I prefer explicit connections. In case you rename GUI objects the compiler will help you finding the places where you have to adjust your C++ code. Connecting by name will find faults only when you open your dialog.

Best regards
ars

anda_skoa
21st February 2016, 13:24
ars already explained the situation and its solutions but just to be more precise: your error message are actually two error messages.

The first line is from the "connected by name" feature and complains that there is no signal with the name "valuechanged" on object sizeslider, because it only has "valueChanged" (capitalization error).

The second and third line are from the connect() statement, since you had "int value" in your SLOT macro, but it only expects argument types, so just "int".

And of course I also fully agree with ars' assessment regarding using "connect by name". I.e. I would also always use and recommend explicit connect.

Cheers,
_

k3ro
21st February 2016, 17:33
Best regards
ars



Cheers,
_

Thanks both for the help. I made the connections explicit and removed the int value mistake and the program now runs without errors.

I have an additional question if you don't mind, because now the program crashes (error message is "the program has unexpectedly finished") whenever the sliders are moved. The functions are very simple (as you can see from my first post I'm just trying to change the text of a qlabel as the slider moves) and I can't figure out why they're crashing. Any suggestions would be appreciated.

(Also, this is relatively unimportant, but any ideas why
sizeslider->TicksAbove; doesn't work?)

Thanks.

P.S. anda_skoa sorry about the dupe thread.

d_stranz
21st February 2016, 18:18
I can't figure out why they're crashing.

If you built a debug version of your program and ran it in the debugger, you would know immediately. If you don't know how to use a debugger, learn. It is an invaluable tool for programming.

My guess is that your valueChanged() / on_valueChanged() signal and slot pair is recursive. As soon as you move a slider, it emits the valueChanged() signal. Your slot handles it and does something in the slot that results in a new valueChanged() signal, which recursively calls your slot, ad infinitum until you get a stack overflow.

k3ro
21st February 2016, 18:37
Thanks all. The crashing issue was due to pointer errors.

anda_skoa
21st February 2016, 18:40
I have an additional question if you don't mind, because now the program crashes (error message is "the program has unexpectedly finished") whenever the sliders are moved. The functions are very simple (as you can see from my first post I'm just trying to change the text of a qlabel as the slider moves) and I can't figure out why they're crashing. Any suggestions would be appreciated.

Is "sizechoice" a valid pointer?



(Also, this is relatively unimportant, but any ideas why
sizeslider->TicksAbove; doesn't work?)

What does "doesn't work" mean in this context?

Enum values are more commonly accessed through qualifying the name by prefixing the class name, not the object, so the equivalent to your code would be


QSlider::TicksAbove;

Which of course doesn't to anything by itself, so it cannot not work.
Did you mean your code did not compile?

Cheers,
_

k3ro
21st February 2016, 20:00
x

Yes, the crashing was due to pointer problems, it is fixed now.

Thanks for pointing out my ticks mistake. I now realise the correct syntax is


sizeslider->setTickPosition(QSlider::TicksAbove);

Thanks all for the help. This thread can be closed now if need be.

k3ro
22nd February 2016, 12:17
Sorry for double post, but I can't find edit button?

I have a final question. Can someone please clarify for me. These are two slots I have, which I have explicitly connected.

.h:

public slots:
void create_chara_triggered();
void exit_now();

.cpp:

QObject::connect(createbutton, SIGNAL(clicked()), this, SLOT(create_chara_triggered()));
QObject::connect(exitbutton, SIGNAL(clicked()), this, SLOT(exit_now()));

void MainWindow::exit_now(){
this->close();
}

void MainWindow::create_chara_triggered(){
Dialog mDialog;
mDialog.exec();
}


They are both almost identical. The createbutton slot works, but it says there is no exit_now slot in mainwindow. I honestly don't understand why sometimes slots just don't seem to work? I've tried renaming a few times, and cleaning/rebuilding. My errors previously in the thread were due to connecting by name and trying to pass 'int value' instead of just 'int' into the slot, but this isn't relevant here. Especially when createbutton works when it's been coded in almost exactly the same way.

Thanks again.

edit: after some browsing I feel like the issue is with the moc files. I'm writing this code in visual studio and the moc files are supposed to be automatically generated. I'm not sure how to force them to regenerate, so I guess this is where the problem is.

anda_skoa
22nd February 2016, 12:55
Usually moc files are regenerated when the header file used as their input changes.

Maybe the Visual Studio Addin has bad change tracking.

In this particular case you don't even needt the slot, as close() is a slot and you can directly connect the exit button to close.

Cheers,
_

k3ro
22nd February 2016, 13:23
Usually moc files are regenerated when the header file used as their input changes.

Maybe the Visual Studio Addin has bad change tracking.

In this particular case you don't even needt the slot, as close() is a slot and you can directly connect the exit button to close.

Cheers,
_

I'm planning on adding more lines to the function once it is working, I need to set a bool when the exit button is clicked, so I can't just connect this button to exit().

I tried deleting q_object and adding it back to force the moc files to generate again. I also tried deleting all moc/ui files to force regenerate, also didn't work.

In the end, I had to copy all of my code into qt creator, recompile, and then import it back into VS. A lot of hassle simply to add a slot, but oh well...