I am using C++ and Qt in my project and my problem is QObject::connect function doesn't connect signal to a slot. I have the following classes:
class AddCommentDialog : public QDialog
{
Q_OBJECT
public:
...some functions
signals:
void snippetAdded();
private slots:
void on_buttonEkle_clicked();
private:
Ui::AddCommentDialog *ui;
QString snippet;
};
A part of my Main window:
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();
private slots:
void commentAddedSlot();
void variableAddedSlot();
...
private:
AddCommentDialog *addCommentDialog;
...
};
Ant the last dialog;
class AddDegiskenDialog : public QDialog
{
Q_OBJECT
public:
...
signals:
void variableAdded();
private slots:
void on_buttonEkle_clicked();
private:
Ui::AddDegiskenDialog *ui;
...
};
In the main window constructor i connect signals and slots:
addCommentDialog=new AddCommentDialog();
addDegiskenDialog=new AddDegiskenDialog();
connect(addDegiskenDialog, SIGNAL(variableAdded()), this, SLOT(variableAddedSlot()));
connect(addCommentDialog, SIGNAL(snippetAdded()), this, SLOT(commentAddedSlot()));
The point is my commentAddedSlot is connected to it's signal successfully, but commentAddedSlot is failed.
There is the Q_OBJECT macros, no warning such as about no x slot. In addition to this,
receivers(SIGNAL(snippetAdded())) gives me 1 but receivers(SIGNAL(variableAdded())) gives me 0 and i used commands qmake -project; qmake and make to fully compile.
What am i missing?
Quick look at your code gives no ideas what is your problem.
But, here are some moments:
As Mike said here: With connection problems, always make sure that you check the console for messages about connect failures. Since Qt can't tell if a connection makes sense until runtime, it notifies you of failures there. You'd think it would crash, but it just quietly says these things in the console.
With Qt, it makes sense to watch the console always. Qt prints out all sorts of error messages that can help when you've got a problem.
You can control result of connect function, so (from official documentation)
The function returns true if it successfully connects the signal to
the slot. It will return false if it cannot create the connection, for
example, if QObject is unable to verify the existence of either signal
or method, or if their signatures aren't compatible.
Check if your objects (dialogs) creates well and pointers is not equal to NULL.
Try to clear your project ("Clear project" command in QtCreator), even manually delete all ui_*, moc_*. And then recompile it.
Good luck! And, please, give us feedback.
Related
I am learning Qt, and I have come up with a problem. I would like some help, here as I tried changing variables and debugging it, but haven't come up with a solution. I'll provide some code to understand the problem i have
In my ColorButton.h class file
class ColorButton : public QToolButton
{
Q_OBJECT
public:
explicit ColorButton(const QColor &color, QWidget *parent = 0);
void testMethod();
};
My ColorButton.cpp file is like this
ColorButton::ColorButton(const QColor &color, QWidget *parent)
{
//some code
}
void ColorButton::testMethod()
{
//This is
//a test method
}
I am trying to access this testMethod() from another class.
From this class, header file is Toolbar.h
class ToolBar : public QToolBar
{
Q_OBJECT
public:
explicit ToolBar(const QMap<ToolsEnum, QAction*> &actionMap, QWidget *parent = 0);
private:
void setToolbar(); //initialize items
ColorButton *test; //-----
public slots:
void setMainColorView();
}
The Toolbar.cpp file is like this
ToolBar::ToolBar(const QMap<ToolsEnum, QAction *> &actionMap, QWidget *parent) :
QToolBar(tr("Tools"),parent), actionMapVar(actionMap)
{
setToolbar();
}
void ToolBar::setToolbar()
{
test = new ColorButton(QColor("#8C001A"));
}
void ToolBar::setMainColorView()
{
test->testMethod();
}
}
The program works when i put test->testMethod(); into setToolbar() , but I want to create the object in setToolbar() and call the method in setMainColorView().
So far I have tried making the Color button variable public,
I have also tried initializing the object called test in the constructor, but both don't work.
Right now, with this code the error I get is
"The inferior stopped because it received a signal from the operating system.
Signal name: SIGSEGV
Signal meaning: Segmentation fault"
with an arrow pointing at test->testMethod(). I have no clue how to solve it, any help would be appreciated
I was looking at the wrong place the entire time. I solved this by passing my toolbar object into the class i was calling setMainColorView() from. In that class i made a local variable of the toolbar object, assigned this. And then it worked.
I have a superclass BackgroundWorkerWithWaitDialog that manages a WaitDialog that implements a progress bar box with an "abort" button. It is used as a QObject in a QThread.
My intention is to derive any background task from BackgroundWorker and implement only the execute() command, polling for an aborted flag to stop it.
BackgroundWorkerWithWaitDialog is derived from BackgroundWorker that is a QObject, all classes are Q_OBJECT and the worker classes are able to update the gui using signals and slots. This communication (Worker to Gui Object) is working correctly.
The problem is that though WaitDialog responds to the pushbutton click, the aborted() signal is emitted from the WaitDialog but isn't received by the BackGroundWorker. (Gui -> Worker)
class WaitDialog : public QDialog
{
Q_OBJECT
public:
explicit WaitDialog(QWidget *parent = 0);
~WaitDialog();
public slots:
void setText(QString text);
void setProgress(bool shown, int max);
void enableAbort(bool enable);
void setProgression (int level);
signals:
void aborted();
private slots:
void on_cmdAbort_clicked();
private:
Ui::WaitDialog *ui;
};
void WaitDialog::on_cmdAbort_clicked()
{
qDebug() << "ABORT";
emit aborted();
}
...
/// BackgroundWorker is QObject-derived.
class BackgroundWorkerWithWaitDialog : public BackgroundWorker
{
Q_OBJECT
public:
explicit BackgroundWorkerWithWaitDialog(MainWindow *main, WaitDialog *dialog);
...
public slots:
virtual void abortIssued();
....
BackgroundWorkerWithWaitDialog::BackgroundWorkerWithWaitDialog(MainWindow *main, WaitDialog *dialog)
: BackgroundWorker(main),
mWaitDialog(dialog),
mAborted(false)
{
connect (this, SIGNAL(progress(int)), mWaitDialog, SLOT(setProgression(int)));
connect (this, SIGNAL(messageChanged(QString)), mWaitDialog, SLOT(setText(QString)));
connect (this, SIGNAL(progressBarVisibilityChanged(bool,int)), mWaitDialog, SLOT(setProgress(bool,int)));
connect (this, SIGNAL(abortButtonVisibilityChanged(bool)), mWaitDialog, SLOT(enableAbort(bool)));
connect (mWaitDialog, SIGNAL(aborted()), this, SLOT(abortIssued()));
}
void BackgroundWorkerWithWaitDialog::abortIssued()
{
// THIS IS NEVER EXECUTED
mAborted = true;
}
Is there something I am missing? I temporarily fixed this with a listener pattern, but frankly I don't like this hybrid fix.
Why isn't the abortIssued slot not called ?
Thanks in advance.
So to summarize:
BackgroundWorkerWithWaitDialog (BWWWD) derives from BackgroundWorker that inherits from QObject
BackgroundWorkerWithWaitDialog receive in the constructor a WaitDialog (WD) that is derived from QDialog
BWWWD in the constructor connect()s the waitDialog aborted() signal with the abortIssued() slot
WD emits the signal but abortIssued isn't called
BWWWD is executed in a separate QThread
It would worth saying that BWWWD class is derived by other SpecificWorker classes that implements specific functions that make use of the aborted() function to interrupt the processing.
Your question states:
i have a superclass BackgroundWorker that manages a WaitDialog that implements a progress bar box with an "abort" button.
In the BackgroundWorkerWithWaitDialog constructor you do not pass dialog to BackgroundWorker's constructor, nor do you use a BackgroundWorker member variable when you are setting up your connections.
Either your questions opening statement is wrong, or you are connecting to a dialog that is never used.
I have problem with actually running QActions created with QtCreator. To run e.g. actionSystemSettings, I've added slot to MainWindows so it looks like this:
namespace Ui {
class MainWindow;
}
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();
private slots:
void on_menuWork_actionSystemSettings();
private:
Ui::MainWindow *ui;
};
And this:
void MainWindow::on_menuWork_actionSystemSettings() {
qDebug() << "Yay!";
}
It prompts:
QMetaObject::connectSlotsByName: No matching signal for
on_menuWork_actionSystemSettings()
I guess it's some dumb mistake and I just forgot about something but reading documentation gives me nothing. I have no "go to slot" menu entry which should auto-create some template... at least Visual Studio for C# did that.
When you're defining slots the correct way is:
on_<widget_name>_<signal>
for instance if you have to name your slot
private slots:
on_actionSystemSettings_triggered();
See QtAutoConnect
According to the documentation for QMetaObject::connectSlotsByName():
Searches recursively for all child objects of the given object, and
connects matching signals from them to slots of object that follow the
following form:
void on_object-name_signal-name(signal-parameters);
So, I think your slot should have the following signature:
void MainWindow::on_actionSystemSettings_triggered()
{
//
}
in python we write custom slots quite easily by passing in the function to be called when a signal is generated.
While in C++ connect function requires us to pass the address of the slot function or so i figured. How do i do that. I tried using this but did'nt work.
Python code::
class imviu(QtGui.QWidget):
def __init__(self):
super(imvui,self).__init__()
self.btn=QtGui.QPushButton('Browse')
btn.clicked.connect(self.openimg)
def openimg(self):
#do something
C++ code::
class imviu: public QWidget
{
public:
imviu(QWidget *parent=0);
QPushButton *btn=new QPushButton("Browse");
void openimg(void);
};
imviu::imviu(QWidget *parent)
:QWidget(parent)
{
connect(btn, SIGNAL(clicked()),this,SLOT(openimg()));//this does'nt work:QObject::connect: No such slot QWidget::openimg()
}
void imviu::openimg()
{
//do something
}
In order to use signals and slots, you need to have the Q_OBJECT macro in your class as well as identifying which functions should be the signals and the slots. Have a look at the documentation for a more in-depth explanation.
After this, you need to set up the project file so that MOC can generate the necessary code.
Your class definition should look like this:
class imviu: public QWidget
{
Q_OBJECT
public:
imviu(QWidget *parent=0);
public slots:
void openimg();
private:
QPushButton *btn;
};
I know there are many many questions that are just the same, but none of them helps me:
class Form1 : public QMainWindow {
Q_OBJECT
public:
Form1();
virtual ~Form1();
public slots:
void langChange(const char* lang_label);
private:
Ui::Form1 widget;
void setLangStrings();
};
From1 constructor:
Form1::Form1() {
widget.setupUi(this);
connect(widget.btnL0, SIGNAL(clicked(bool)), this, SLOT(langChange("en")));
connect(widget.btnL1, SIGNAL(clicked(bool)), this, SLOT(langChange("fr")));
setLangStrings();
}
And I also have this langChange function implemented:
void Form1::langChange(const char* lang_label)
{
GL_LANG = lang_label;
setLangStrings();
}
I get this stupid error when the connect function is called:
No such slot Form1::langChange("sl") in Form1.cpp:15
I'm using NetBeans with QDesigner for the UI. I must say this QT4 is very difficult to learn.
You simply can't connect SIGNAL with bool as argument to SLOT with const char* as argument. To do this kind of stuff you have to use QSignalMapper. You have an example how to use it inside documentation. In your case, it's very simple, so you should handle it easly.
The SLOT function must have the same signature than the SIGNAL function
Edit: From the official Qt documentation (http://qt-project.org/doc/qt-4.8/signalsandslots.html):
The signature of a signal must match the signature of the receiving
slot. (In fact a slot may have a shorter signature than the signal it
receives because it can ignore extra arguments.)