4
votes

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 main 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?

4
Is you moc file alright ? Can you see your slot in the qt_metacall(QMetaObject::Call _c, int _id, void **_a) ?Thomas Vincent
Yeah, it's in there. It should all be defined.user850275
A couple questions for clarification.. Which slot is named in the error message for "No such slot"? How is the "Accept" slot called?Arnold Spence
Object::connect: No such slot MainWindow::SetVal(double x)user850275
@user850275: Either you misquoted the error message, or you miscopied your code. The error message should be No such slot: MainWindow::SetVal(double) (without the x). If the error message is correct, and your code is really SLOT(SetVal(double x)), then you can fix the problem by removing the x.TonyK

4 Answers

7
votes

For me, adding a public Q_SLOTS: above my slot function was what I was missing. (I already had Q_OBJECT, etc.)

3
votes

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.

2
votes

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.

0
votes

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