Problem is that I keep getting the 'No Such Slot' runtime error in Qt Creator every time I launch a 'settings' window from my main window. I've found Qt to be quite counter-intuitive so far and this slots 'n signals concept seems a bit of a stretch from simply passing vars or function calls. Basically, I have menu with a settings option, that when clicked, opens a settings window which needs to grab a double from the user and update a var in the main window.
SettingsWindow.h
class SettingsWindow : public QWidget
{
Q_OBJECT
public:
SettingsWindow(QWidget *parent = 0);
signals:
void ValChanged(double newVal);
public slots:
void Accept();
private:
QLineEdit *le1;
};
The settings window has an accept button which calls Accept() which emits the ValChanged signal with newVal set as the user input in le1 as a double.
SettingsWindow.cpp
void SettingsWindow::Accept(){
emit ValChanged(le1->text().toDouble());
this->close();
}
This settings window is called by the application's main window: MainWindow
MainWindow.cpp
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
MainWindow(QWidget *parent = 0);
public slots:
void SetVal(double x);
private slots:
void NewWindow();
private:
double theVal;
};
This ma开发者_运维知识库in window has a menu which one would select settings from. This creates a new window with a field for one to enter a number.
MainWindow.cpp
void MainWindow::NewWindow()
{
SettingsWindow *MySettings=new SettingsWindow(this);
QObject::connect(MySettings, SIGNAL(ValChanged(double)), this, SLOT(SetVal(double)));
MySettings->show();
MySettings->raise();
}
void MainWindow::SetVal(double x){
theVal = x;
}
My hope is that when the settings window is opened, the user can enter a val into the field which then emits the ValChanged Signal which sets theVal to the value specified by the user. Most of the time I saw an issue with people not including Q_OBJECT macro, but I've included it both times. Any suggestions on why this doesn't work?
For me, adding a public Q_SLOTS:
above my slot function was what I was missing. (I already had Q_OBJECT, etc.)
The issue you are having is almost certainly due to a moc file not being recreated, a typo in your call to connect or a typo in the declaration of the slot in question.
You may want to consider that this is a lot more work than necessary for getting input from a dialog. A simpler method would be to connect the "Accept" button clicked signal to a slot in main window and then fetch the value you want directly from the instance of the settings window through a getXXX()
method.
If you eventually have a settings dialog with a lot of values, instead of fetching each value through getters, have the "Accept" button signal return a structure with all the values as fields of that structure.
I should mention that it looks like NewWindow()
creates a new instance of SettingsWindow
each time it is called. All of these instances will persist until the MainWindow
is destroyed.
I solved my problem when I manually recreated my moc file on the command line.
I used qt command prompt option so all the paths had been set:
cd /path/to/my/project
moc -o moc_myheaderfile.cpp myheaderfile.h
There was nothing wrong with my code, and my makefile didn't have any moc command I could see. This works for all my examples I have tried. I hope someone might try this too. I experimented for almost 85 hours before I could find the cause.
For codeblocks users, try recreating your moc files to be precise.
the -o myheaderfile.cpp
option is to save the moc output to a file.
Running moc on the file actually spews everything onto the console window.
I was incorrectly trying to pass a parameter to my slot without a QSignalMapper
, which I learned from this SO post.
Removing all parameters to the slot function (.h and .cpp) allowed the callback to be found and called.
Yes, I'm a Qt n00b. Time to refactor with QSignalMapper :)
HTH
精彩评论