c++ QPushButton signal and slot - c++

I have a problem creating a QPushButton and linking its signal to my slots. First, I created a class with the slot:
class A : public QWidget{
public slots:
void handleButton();
};
There is my handleButton function in the .cpp
void A::handleButton(int row, int col){
m_button->setText("Example");
// resize button
m_button->resize(100,100);
}
Then I want to connect the button.
QObject::connect(m_button, SIGNAL(clicked()), qApp, SLOT(handleButton()));
But I got an error when I start the application:
"No such slot"

Make sure that qApp is an object of class A (i.e. where your slot is defined).
That said, the signatures are wrong: a signal links to a slot only if the signature match
http://qt-project.org/doc/qt-4.8/signalsandslots.html
The signals and slots mechanism is type safe: The signature of a signal must match the signature of the receiving slot.
And your slot hasn't the right signature:
http://qt-project.org/doc/qt-4.8/qabstractbutton.html#clicked
void QAbstractButton::clicked ( bool checked = false ) [signal]

You have a few errors in this code, if you define "void handlebutton()" then you must implement void handlebutton() NOT void handlebutton(inx x, int y) this code should not even compile.
More: in QT you CAN ONLY connect SIGNALS and SLOTS with the same parameters so you can connect SIGNAL(clicked()) with SLOT(handlebutton()) but not SIGNAL(clicked() with SLOT(handleButton(int, int)).
Another problem is that connect is executed at runtime so You must compile and run before Qt can show you the error.
So a possible solution is:
define and implement the slot void handlebutton() and connect that to the signal clicked(), then define another method handleButton (int x, int y) that you will call from inside handleButton().
I really hope that makes sense to you.

Your class definition should look like :
class A : public QWidget
{
Q_OBJECT
public slots:
void handleButton(int, int);
};
And you should connect it like:
QObject::connect(m_button, SIGNAL(clicked()),qApp, SLOT(handleButton(int a, int b)));
where a and b are variables for row and column.
This should work. Try understanding basic C++. :)

Related

Qt connect signal with another class method

I have class
class Files : public QWidget
{
Q_OBJECT
public:
Files();
~Files();
public slots:
void saveFile(Ui::MainWindow * ui);
void openFile(Ui::MainWindow * ui);
void checkOpenFile(Ui::MainWindow * ui);
void newFile(Ui::MainWindow * ui);
void checkNewFile(Ui::MainWindow * ui);
void closeFile(Ui::MainWindow * ui);
};
and i want to connect button placed in MainWindow class with slot void newFile(Ui::MainWindow * ui) of Files class
i tried
files = new Files;
//files->newFile(ui); works as it should
connect(ui->actionExit, SIGNAL(triggered()), files, SLOT(closeFile(ui)));
and I have message:
QObject::connect: No such slot Files::closeFile(ui) in ../qt/src/core/mainwindow.cpp:16
QObject::connect: (sender name: 'actionExit')
How should i connect ui->actionExit with Files::closeFile(ui) slot the right way?
First, you are attempting to connect signal and slot which are not compatible with each other: closeFile slot requires a parameter of Ui::MainWindow * type but the signal which you are attempting to connect to it has no parameters.
Do you really need closeFile to take a pointer to Ui::MainWindow? Can you instead make this and other slots take no parameters? If you really need to access Ui::MainWindow from inside methods/slots within Files, you can just create a setter to pass the pointer to Ui::MainWindow to Files and use that pointer in slots which themselves won't take any parameters.
Second, you are trying to use old, obsolete and slow method of setting up connections between signals and slots. This method is not only bad because it's slow but it is also bad because it only shows you errors during runtime i.e. when you compile and launch your app. If you used pointer to member function based connection syntax, it would refuse to compile should you try to connect incompatible signals and slots. It is much better this way because you can see and fix the errors early.

QT connect signal and slot in from different classes to mainwindow class?

I want to implement signal and slot between two classes mainwindow and reader.
Inside the reader class I declare the signal SetProgress:
reader.h
class reader :public QObject
{
Q_OBJECT
signals:
void SetProgress(QString sOperation, int nPercentage);
}
reader.cpp
void reader::UpdateProgress(double amount)
{
int nPrecentage = (100 * amount / (max- min));
emit SetProgress(m_sCurrentOperation, nPrecentage);
}
mainwindow.h
public:
reader *MyReader
private slots:
void SlotDisplayProgress(QString sActivity_i, int ProgressPercentage_i);
mainwindow.cpp
void mainwindow :: SlotDisplayProgress(QString sActivity_i, int nProgressPercentage_i)
{
this->ui->QprogressBar->setValue(nProgressPercentage_i);
}
inside Mainwidow.cpp I will declare signal and slot
MyReader = reader::New();
connect ( MyReader, &reader::SetProgress, this, &mainwindow::SlotDisplayProgress );
I tried debugging and everything works correctly till the emit part. However, the slot is never executed.
Try setting Qt::DirectConnection:
connect ( MyReader, &reader::SetProgress, this, &mainwindow::SlotDisplayProgress, ***Qt::DirectConnection***);
I had a problem like this, where I connected the signal and slot, and it only worked when I defined the type of connection.
I hope this helps.
PS. I don't know if this depends on the version of QT but when I connect signals and slots the syntax I write is the following:
ImageURLLoadListener* downloader = new ImageURLLoadListener(&id, socket);
connect(downloader, SIGNAL(imageLoaded(QString*,QTcpSocket*)), this, SLOT(on_resourceImageDownload(QString*,QTcpSocket*)), Qt::DirectConnection);
I don't know if it's related or not...
Is MyReader pointer? Use &MyReader if not so.

using another class object for signal and slots inside qt

Consider the following scenario:
I have integrated QT in my c++ app. I wish to enter Data from a GUI rather than terminal. For this purpose, i created a function for QT. My dialog window consists of three text lines and a button, upon the click of which i want to call a particular method of some other class. I am having trouble with SINGAL and SLOTS.
Consider the following files:
main.cpp has
a.h -> a.cpp
a.cpp has
a.h
myslots.h
and the QT app method inside a.cpp as:
int A::inputData(){
...
A a
myslots ms;
QObject::connect(button, SIGNAL(clicked()), &ms, SLOT(clickButton(&a)));
....
}
myslots.h has:
a.h and inherited from A as:
class myslots : public QObject, public A {
Q_OBJECT
public slots:
void clickButton(A &a);
signals:
void buttonClicked();
};
myslots.cpp has:
myslots.h and the following method
void myslots::clickButton(A &a) {
cout <<"I am called successfully"<<endl;
a.perform_action(-2.3, 4.5, 4.4);
emit this->buttonClicked();
}
I get the following error:
QObject::connect: No such slot myslots::clickButton(&a)
Actually i want to pass three double values from three textlines say: 1.3, 2.4, 4.5 to a function by clicking the button, where the function to be called is in another class that is inherited by myslots.h and accepts three parameters.
Currently am just testing whether i am able to call the function properly or not but am not.
Thanks
This will not work. In SIGNAL or SLOT must be a type, not an object or its reference. I mean this
QObject::connect(button, SIGNAL(clicked()), &ms, SLOT(clickButton(&a)));
must be
QObject::connect(button, SIGNAL(clicked()), &ms, SLOT(clickButton(A)));
But then you must catch another error - where is A in your SIGNAL? Why do you use A in the signal at all?
Some issues:
1 - When tou derive from QObject, always put the Q_OBJECT macro in the private section of your class, do something like
class MyClass: public QObject {
Q_OBJECT
public:
...
this Q_OBJECT macro is important for classes that have signals and slots.
2 - In the connect statement you have to tell Qt the type of the parameters, not the names you use, that is, if you slot function is
void myslots::clickButton(A &a);
The you connect to it with
connect(emiterObject, SIGNAL(someSignal(A)), targetObject, SLOT(clickButton(A)));
Since Qt 5.x you are able to use a lambda expression as slot.
So your connect statement should look like:
QObject::connect(button, &QPushButton::clicked, [a, ms](){ms.clickButton(&a);});
But, using a and ms as local variables is not realy a good thing, as stated by Karsten Koop.
The error is in your :
QObject::connect(button, SIGNAL(clicked()), &ms, SLOT(clickButton(&a)));
it has to be:
QObject::connect(button, SIGNAL(clicked(A)), &ms, SLOT(clickButton(A)));
the type that you send in the SIGNAL must be in SLOT that receives that type.

Qt4: connect slot and signal from other forms

I have a small problem. I want run function in MainWindow from AnotherWindow. I can't set connect() for it.
Main class: MainWindow
Other form: AnotherWindow
Function in main class: setVariable(QString)
Function in other form: btnClicked()
I have now connected button signal clicked():
// In AnotherWindow.cpp
connect(ui->btnOK, SIGNAL(clicked()), this, SLOT(btnOkClicked()));
// Function in same file
void interfaceWindow::btnOkClicked() {
/* Some actions - emit signal? */
this->close();
}
btnOkClicked() are declared as private slot.
// In MainWindow.cpp
void MainWindow::setVariable(QString _var) {
this->var = _var;
}
setVariable(QString) are declared as public slot.
How I can send variable from AnotherForm (from btnOkClicked() function) to MainWindow (setVariable(QString) function) ? How and where I must send signal and make connection?
I readed about signals and slots, but my code don't work - I don't paste it here because it's terrible :)
Any help for Qt newbie?
You need to have an reference of AnotherWindow in MainWindow OR vice versa. Then you need the following things:
// AnotherWindow.h
signals:
void buttonOkClickedSignal(QString var);
// AnotherWindow.cpp
void interfaceWindow::btnOkClicked() {
emit buttonOkClickedSignal("The button got clicked!");
this->close();
}
Next step varies based on whether MainWindow has reference to AnotherWindow or vice versa. You can either:
// AnotherWindow.cpp
connect(this, SIGNAL(buttonOkClickedSignal(QString), &mainWindow, SLOT(setVariable(QString)));
or:
// MainWindow.cpp
connect(&anotherWindow, SIGNAL(buttonOkClickedSignal(QString), this, (SLOT(setVariable(QString)));
If you are invoking the slot through signal it shouldn't matter whether it's private or public (see Qt Documentation).
Hope this helps.
I'm not entirely sure I understand your question, but let me try.
You want to be able to fire a slot in another class. There are a few ways you can do that.
Declare one as a friend class to the other. Then they can see the protected and private variables/memebers
It is possible to make slots static so you can call them without a class object.
For example,
class MainWindow {
private slot:
void setVariable(QString);
}
class AnotherWindow {
friend class MainWindow;
MainWindow *window;
public:
AnotherWindow() {
connect(this, SIGNAL(fire(QString)), window, SLOT(setVariable(QString)));
}
signals:
void fire(QString);
public slots:
void onButtonClicked() {
emit fire(QString);
}
}
The previous is pseudocode so don't expect it to compile. I think this is what you want. Basically since your slot is private on MainWindow you need to make it a friend. To connect, it needs to be a member. Then when the onButtonClicked slot is evoked, then it fire()s the setVarialbe() slot.
Here is a simple code for your another window:
class MyWidget : public QWidget
{
Q_OBJECT
public:
MyWidget(QWidget * parent = 0)
{
okBtn = new QPushButton ("I am Ok!");
MyData = "";
connect(okBtn ,SIGNAL(clicked()),this,SLOT(OnOk()));
}
~MyWidget();
private:
QString MyData;
QPushButton * okBtn;
//something that modify string MyData
signals:
void MyDataSignal(QString);
//Internal slot that emits signal with proper data
private slots:
void OnOk()
{
if(MyData!="")
{
emit MyDataSignal(MyData);
}
}
};
Now in MainWindow create an object of MyWidget (suppose myWid)and connect it to slot
connect(myWid, SIGNAL(MyDataSignal(QString)),this,SLOT(OnMyWidOkClicked(QString)));
the signal will pass string to slot.
While making signals and slots keep in mind following points:
To connect a signal to a slot (or to another signal), they must have the same parameter
Parameters should be in the same order in both signal and slot.
if a signal has more parameters than the slot it is connected to, the additional parameters are simply ignored but opposite is not possible.
If you will connect a signal that have unmatched parameters to slot then no compile time error will occur but at run time command window will show a warning that signal/slot/connection does not exist.

QT4 no such slot error

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.)