Qt for beginners Signals and slots 2: Difference between revisions

From Qt Wiki
Jump to navigation Jump to search
No edit summary
No edit summary
Line 1: Line 1:
[toc align_right=&quot;yes&amp;quot; depth=&quot;3&amp;quot;]<br />[[Category:Qt_for_beginners]]<br />[[Category:Tutorial]]<br />[[Category:HowTo]]
[toc align_right="yes" depth="3"]
[[Category:Qt_for_beginners]]
[[Category:Tutorial]]
[[Category:HowTo]]


= Qt for beginners — Signals and slots 2 =
= Qt for beginners — Signals and slots 2 =


[[Qt_for_beginners_Signals_and_slots|&lt;&lt;&lt; Signals and slots]] | [[Qt_for_beginners|Summary]] | [[Qt_for_beginners_Exercise_1_basis|Exercise 1 : basis &gt;&gt;&gt;]]
[[Qt_for_beginners_Signals_and_slots|<<< Signals and slots]] | [[Qt_for_beginners|Summary]] | [[Qt_for_beginners_Exercise_1_basis|Exercise 1 : basis >>>]]


'''''Note:''' Unfortunately, the images are no longer available. See the official &quot;Getting Started with Qt Widgets&amp;quot;:http://doc.qt.io/qt-5/gettingstartedqt.html page for an alternative tutorial.''
'''''Note:''' Unfortunately, the images are no longer available. See the official "Getting Started with Qt Widgets":http://doc.qt.io/qt-5/gettingstartedqt.html page for an alternative tutorial.''


This chapter covers the second part of signals and slots : implementing custom signals and slots.
This chapter covers the second part of signals and slots : implementing custom signals and slots.
Line 37: Line 40:
They are emitted using the '''emit''' keyword :
They are emitted using the '''emit''' keyword :


<code><br />emit mySignal();<br /></code>
<code>
emit mySignal();
</code>


Note that in order to send signals that have parameters, you have to pass them in the signal emission
Note that in order to send signals that have parameters, you have to pass them in the signal emission


<code><br />emit mySignal(firstParameter, secondParameter …);<br /></code>
<code>
emit mySignal(firstParameter, secondParameter …);
</code>


== Example ==
== Example ==
Line 49: Line 56:
Let's start with our window with the button :
Let's start with our window with the button :


''window.h''<br /><code><br />#ifndef WINDOW_H<br />#define WINDOW_H
''window.h''
<code>
#ifndef WINDOW_H
#define WINDOW_H


#include &lt;QWidget&amp;gt;
#include <QWidget>


class QPushButton;<br />class Window : public QWidget<br />{<br />public:<br /> explicit Window(QWidget *parent = 0);<br />private:<br /> QPushButton *m_button;<br />};
class QPushButton;
class Window : public QWidget
{
public:
explicit Window(QWidget *parent = 0);
private:
QPushButton *m_button;
};


#endif // WINDOW_H<br /></code>
#endif // WINDOW_H
</code>


''window.cpp''<br /><code><br />#include &quot;window.h&amp;quot;
''window.cpp''
<code>
#include "window.h"


#include &lt;QPushButton&amp;gt;
#include <QPushButton>


Window::Window(QWidget *parent) :<br /> QWidget(parent)<br />{<br /> // Set size of the window<br /> setFixedSize(100, 50);
Window::Window(QWidget *parent) :
QWidget(parent)
{
// Set size of the window
setFixedSize(100, 50);


// Create and position the button<br /> m_button = new QPushButton(&quot;Hello World&amp;quot;, this);<br /> m_button-&gt;setGeometry(10, 10, 80, 30);<br />}<br /></code>
// Create and position the button
m_button = new QPushButton("Hello World", this);
m_button->setGeometry(10, 10, 80, 30);
}
</code>


We might want to remove our previous connection that makes the application quit while clicking on the button. Now, we want that, when clicking on the button, the text is changed. More precisely, we want that the button can be ''checked'', and that, when checked, it displays &quot;checked&amp;quot;, and when unchecked, it restores &quot;Hello World&amp;quot;.
We might want to remove our previous connection that makes the application quit while clicking on the button. Now, we want that, when clicking on the button, the text is changed. More precisely, we want that the button can be ''checked'', and that, when checked, it displays "checked", and when unchecked, it restores "Hello World".


QPushButton does not implement such a specific slot, so we have to implement it on our own. As stated previously, we have to add the '''Q_OBJECT''' macro.
QPushButton does not implement such a specific slot, so we have to implement it on our own. As stated previously, we have to add the '''Q_OBJECT''' macro.


<code><br />class Window : public QWidget<br />{<br /> Q_OBJECT<br />public:<br /> explicit Window(QWidget *parent = 0);<br />private:<br /> QPushButton *m_button;<br />};<br /></code>
<code>
class Window : public QWidget
{
Q_OBJECT
public:
explicit Window(QWidget *parent = 0);
private:
QPushButton *m_button;
};
</code>


We also add our custom slot. Since we are trying to react from the button being checked, and since the corresponding signal is
We also add our custom slot. Since we are trying to react from the button being checked, and since the corresponding signal is


<code><br />void QPushButton::clicked(bool checked)<br /></code>
<code>
void QPushButton::clicked(bool checked)
</code>


we might implement a slot that has this signature :
we might implement a slot that has this signature :


<code><br />void Window::slotButtonClicked(bool checked);<br /></code>
<code>
void Window::slotButtonClicked(bool checked);
</code>


Most of the time, by convention, we implement private and protected slots by prefixing them with &quot;slot&amp;quot;. Here, we are not interested in exposing this slot as a public function, we can make it private. The new header is then
Most of the time, by convention, we implement private and protected slots by prefixing them with "slot". Here, we are not interested in exposing this slot as a public function, we can make it private. The new header is then


''window.h''<br /><code><br />#ifndef WINDOW_H<br />#define WINDOW_H
''window.h''
<code>
#ifndef WINDOW_H
#define WINDOW_H


#include &lt;QWidget&amp;gt;
#include <QWidget>


class QPushButton;<br />class Window : public QWidget<br />{<br /> Q_OBJECT<br />public:<br /> explicit Window(QWidget *parent = 0);<br />private slots:<br /> void slotButtonClicked(bool checked);<br />private:<br /> QPushButton *m_button;<br />};
class QPushButton;
class Window : public QWidget
{
Q_OBJECT
public:
explicit Window(QWidget *parent = 0);
private slots:
void slotButtonClicked(bool checked);
private:
QPushButton *m_button;
};


#endif // WINDOW_H<br /></code>
#endif // WINDOW_H
</code>


The implementation of this slot is
The implementation of this slot is


<code><br />void Window::slotButtonClicked(bool checked)<br />{<br /> if (checked) {<br /> m_button-&gt;setText(&quot;Checked&amp;quot;);<br /> } else {<br /> m_button-&gt;setText(&quot;Hello World&amp;quot;);<br /> }<br />}<br /></code>
<code>
void Window::slotButtonClicked(bool checked)
{
if (checked) {
m_button->setText("Checked");
} else {
m_button->setText("Hello World");
}
}
</code>


We need to make the button checkable, and establish the connection, we have to add this code in the constructor :
We need to make the button checkable, and establish the connection, we have to add this code in the constructor :


<code><br />m_button-&gt;setCheckable(true);
<code>
m_button->setCheckable(true);


connect(m_button, SIGNAL (clicked(bool)), this, SLOT (slotButtonClicked(bool)));<br /></code>
connect(m_button, SIGNAL (clicked(bool)), this, SLOT (slotButtonClicked(bool)));
</code>


The resulting code is then
The resulting code is then
Line 103: Line 169:
''window.cpp''
''window.cpp''


<code><br />#include &quot;window.h&amp;quot;
<code>
#include "window.h"


#include &lt;QPushButton&amp;gt;
#include <QPushButton>


Window::Window(QWidget *parent) :<br /> QWidget(parent)<br />{<br /> // Set size of the window<br /> setFixedSize(100, 50);
Window::Window(QWidget *parent) :
QWidget(parent)
{
// Set size of the window
setFixedSize(100, 50);


// Create and position the button<br /> m_button = new QPushButton(&quot;Hello World&amp;quot;, this);<br /> m_button-&gt;setGeometry(10, 10, 80, 30);<br /> m_button-&gt;setCheckable(true);
// Create and position the button
m_button = new QPushButton("Hello World", this);
m_button->setGeometry(10, 10, 80, 30);
m_button->setCheckable(true);


connect(m_button, SIGNAL (clicked(bool)), this, SLOT (slotButtonClicked(bool)));<br />}
connect(m_button, SIGNAL (clicked(bool)), this, SLOT (slotButtonClicked(bool)));
}


void Window::slotButtonClicked(bool checked)<br />{<br /> if (checked) {<br /> m_button-&gt;setText(&quot;Checked&amp;quot;);<br /> } else {<br /> m_button-&gt;setText(&quot;Hello World&amp;quot;);<br /> }<br />}<br /></code>
void Window::slotButtonClicked(bool checked)
{
if (checked) {
m_button->setText("Checked");
} else {
m_button->setText("Hello World");
}
}
</code>


And we should get this as a result
And we should get this as a result
Line 123: Line 206:
Based on the previous example, we want to close the application if the button is clicked (checked or unchecked) 10 times. We first need to implement a counter that will count the number of clicks. These modifications implement it
Based on the previous example, we want to close the application if the button is clicked (checked or unchecked) 10 times. We first need to implement a counter that will count the number of clicks. These modifications implement it


<code><br />class Window : public QWidget<br />{<br /> Q_OBJECT<br />public:<br /> explicit Window(QWidget *parent = 0);<br />private slots:<br /> void slotButtonClicked(bool checked);<br />private:<br /> int m_counter;<br /> QPushButton *m_button;<br />};<br /></code>
<code>
class Window : public QWidget
{
Q_OBJECT
public:
explicit Window(QWidget *parent = 0);
private slots:
void slotButtonClicked(bool checked);
private:
int m_counter;
QPushButton *m_button;
};
</code>


and
and


<code><br />Window::Window(QWidget *parent) :<br /> QWidget(parent)<br />{<br /> // Set size of the window<br /> setFixedSize(100, 50);
<code>
Window::Window(QWidget *parent) :
QWidget(parent)
{
// Set size of the window
setFixedSize(100, 50);


// Create and position the button<br /> m_button = new QPushButton(&quot;Hello World&amp;quot;, this);<br /> m_button-&gt;setGeometry(10, 10, 80, 30);<br /> m_button-&gt;setCheckable(true);
// Create and position the button
m_button = new QPushButton("Hello World", this);
m_button->setGeometry(10, 10, 80, 30);
m_button->setCheckable(true);


// Set the counter to 0<br /> m_counter = 0;
// Set the counter to 0
m_counter = 0;


connect(m_button, SIGNAL (clicked(bool)), this, SLOT (slotButtonClicked(bool)));<br />}
connect(m_button, SIGNAL (clicked(bool)), this, SLOT (slotButtonClicked(bool)));
}


void Window::slotButtonClicked(bool checked)<br />{<br /> if (checked) {<br /> m_button-&gt;setText(&quot;Checked&amp;quot;);<br /> } else {<br /> m_button-&gt;setText(&quot;Hello World&amp;quot;);<br /> }
void Window::slotButtonClicked(bool checked)
{
if (checked) {
m_button->setText("Checked");
} else {
m_button->setText("Hello World");
}


m_counter '''';<br />}<br /></code>
m_counter '''';
}
</code>


Now, we have to create a custom signal that is used to notify other components, that the counter has reached 10. In order to declare a signal, we have to add a &lt;code&amp;gt;signals&amp;lt;/code&amp;gt; section in the header. We might also declare a signal with the following signature
Now, we have to create a custom signal that is used to notify other components, that the counter has reached 10. In order to declare a signal, we have to add a <code>signals</code> section in the header. We might also declare a signal with the following signature


<code><br />void Window::counterReached()<br /></code>
<code>
void Window::counterReached()
</code>


The header class is then declared as followed
The header class is then declared as followed


<code><br />class Window : public QWidget<br />{<br /> Q_OBJECT<br />public:<br /> explicit Window(QWidget *parent = 0);<br />signals:<br /> void counterReached();<br />private slots:<br /> void slotButtonClicked(bool checked);<br />private:<br /> int m_counter;<br /> QPushButton *m_button;<br />};<br /></code>
<code>
class Window : public QWidget
{
Q_OBJECT
public:
explicit Window(QWidget *parent = 0);
signals:
void counterReached();
private slots:
void slotButtonClicked(bool checked);
private:
int m_counter;
QPushButton *m_button;
};
</code>


Even if the signal is declared as a method, there is no need to implement it. The meta-object compiler is used to do this.
Even if the signal is declared as a method, there is no need to implement it. The meta-object compiler is used to do this.
Line 151: Line 280:
Now we need to emit the signal when the counter reaches 10. It is simply done in the slot
Now we need to emit the signal when the counter reaches 10. It is simply done in the slot


<code><br />void Window::slotButtonClicked(bool checked)<br />{<br /> if (checked) {<br /> m_button-&gt;setText(&quot;Checked&amp;quot;);<br /> } else {<br /> m_button-&gt;setText(&quot;Hello World&amp;quot;);<br /> }
<code>
void Window::slotButtonClicked(bool checked)
{
if (checked) {
m_button->setText("Checked");
} else {
m_button->setText("Hello World");
}


m_counter '''';<br /> if (m_counter == 10) {<br /> emit counterReached();<br /> }<br />}<br /></code>
m_counter '''';
if (m_counter == 10) {
emit counterReached();
}
}
</code>


We need to write the keyword '''emit''' to send the signal.
We need to write the keyword '''emit''' to send the signal.


Connecting the newly created signal to the &lt;code&amp;gt;quit&amp;lt;/code&amp;gt; slot is done as usual
Connecting the newly created signal to the <code>quit</code> slot is done as usual


<code><br />connect(this, SIGNAL (counterReached()), QApplication::instance(), SLOT (quit()));<br /></code>
<code>
connect(this, SIGNAL (counterReached()), QApplication::instance(), SLOT (quit()));
</code>


The final code is
The final code is


''window.h''<br /><code><br />#ifndef WINDOW_H<br />#define WINDOW_H
''window.h''
<code>
#ifndef WINDOW_H
#define WINDOW_H


#include &lt;QWidget&amp;gt;
#include <QWidget>


class QPushButton;<br />class Window : public QWidget<br />{<br /> Q_OBJECT<br />public:<br /> explicit Window(QWidget *parent = 0);<br />signals:<br /> void counterReached();<br />private slots:<br /> void slotButtonClicked(bool checked);<br />private:<br /> int m_counter;<br /> QPushButton *m_button;<br />};
class QPushButton;
class Window : public QWidget
{
Q_OBJECT
public:
explicit Window(QWidget *parent = 0);
signals:
void counterReached();
private slots:
void slotButtonClicked(bool checked);
private:
int m_counter;
QPushButton *m_button;
};


#endif // WINDOW_H<br /></code>
#endif // WINDOW_H
</code>


''window.cpp''<br /><code><br />#include &quot;window.h&amp;quot;
''window.cpp''
<code>
#include "window.h"


#include &lt;QPushButton&amp;gt;<br />#include &lt;QApplication&amp;gt;
#include <QPushButton>
#include <QApplication>


Window::Window(QWidget *parent) :<br /> QWidget(parent)<br />{<br /> // Set size of the window<br /> setFixedSize(100, 50);
Window::Window(QWidget *parent) :
QWidget(parent)
{
// Set size of the window
setFixedSize(100, 50);


// Create and position the button<br /> m_button = new QPushButton(&quot;Hello World&amp;quot;, this);<br /> m_button-&gt;setGeometry(10, 10, 80, 30);<br /> m_button-&gt;setCheckable(true);
// Create and position the button
m_button = new QPushButton("Hello World", this);
m_button->setGeometry(10, 10, 80, 30);
m_button->setCheckable(true);


// Set the counter to 0<br /> m_counter = 0;
// Set the counter to 0
m_counter = 0;


connect(m_button, SIGNAL (clicked(bool)), this, SLOT (slotButtonClicked(bool)));<br /> connect(this, SIGNAL (counterReached()), QApplication::instance(), SLOT (quit()));<br />}
connect(m_button, SIGNAL (clicked(bool)), this, SLOT (slotButtonClicked(bool)));
connect(this, SIGNAL (counterReached()), QApplication::instance(), SLOT (quit()));
}


void Window::slotButtonClicked(bool checked)<br />{<br /> if (checked) {<br /> m_button-&gt;setText(&quot;Checked&amp;quot;);<br /> } else {<br /> m_button-&gt;setText(&quot;Hello World&amp;quot;);<br /> }
void Window::slotButtonClicked(bool checked)
{
if (checked) {
m_button->setText("Checked");
} else {
m_button->setText("Hello World");
}


m_counter '''';<br /> if (m_counter == 10) {<br /> emit counterReached();<br /> }<br />}<br /></code>
m_counter '''';
if (m_counter == 10) {
emit counterReached();
}
}
</code>


And you can try and check that after clicking the button ten times, the application will quit.
And you can try and check that after clicking the button ten times, the application will quit.
Line 193: Line 377:
While compiling your program, especially when you are adding the macro Q_OBJECT, you might have this compilation error.
While compiling your program, especially when you are adding the macro Q_OBJECT, you might have this compilation error.


&lt;code&amp;gt;<br />main.cpp:(.text._ZN6WindowD2Ev[_ZN6WindowD5Ev]+0x3): undefined reference to `vtable for Window'<br />&lt;/code&amp;gt;
<code>
main.cpp:(.text._ZN6WindowD2Ev[_ZN6WindowD5Ev]+0x3): undefined reference to `vtable for Window'
</code>


This is because of the meta-object compiler not being run on a class that should have meta-object. You should '''rerun qmake''', by doing Build &gt; Run qmake.
This is because of the meta-object compiler not being run on a class that should have meta-object. You should '''rerun qmake''', by doing Build > Run qmake.

Revision as of 08:41, 25 February 2015

[toc align_right="yes" depth="3"]

Qt for beginners — Signals and slots 2

<<< Signals and slots | Summary | Exercise 1 : basis >>>

Note: Unfortunately, the images are no longer available. See the official "Getting Started with Qt Widgets":http://doc.qt.io/qt-5/gettingstartedqt.html page for an alternative tutorial.

This chapter covers the second part of signals and slots : implementing custom signals and slots.

Creating custom slots and signals is really simple. Slots are like normal methods, but with small decorations around. While signals needs little to no implementation at all.

Creating custom signals and slots

Creating custom signals and slots is very simple. It is described by the following checklist

  • add Q_OBJECT macro
  • add signals section, and write signals prototypes.
  • add public slots or protected slots or private slots sections, and write slots prototypes.
  • implement slots as normal methods.
  • establish connections.

Creating custom slots

In order to implement a slot, we first need to make the class be able to send signals and have slots (see previous chapter). This is done by setting the Q_OBJECT macro in the class declaration (often in the header).

After that, a slot should be declared in the corresponding section, and implemented as a normal method.

Finally, slots are connected to signals.

Creating signals

As for slots, we first need to add the Q_OBJECT macro.

Signals should also be declared in the signals section, and there is no need for them to be implemented.

They are emitted using the emit keyword :

emit mySignal();

Note that in order to send signals that have parameters, you have to pass them in the signal emission

emit mySignal(firstParameter, secondParameter );

Example

Creating custom slots

Let's start with our window with the button :

window.h

#ifndef WINDOW_H
#define WINDOW_H

#include <QWidget>

class QPushButton;
class Window : public QWidget
{
public:
 explicit Window(QWidget *parent = 0);
private:
 QPushButton *m_button;
};

#endif // WINDOW_H

window.cpp

#include "window.h"

#include <QPushButton>

Window::Window(QWidget *parent) :
 QWidget(parent)
{
 // Set size of the window
 setFixedSize(100, 50);

// Create and position the button
 m_button = new QPushButton("Hello World", this);
 m_button->setGeometry(10, 10, 80, 30);
}

We might want to remove our previous connection that makes the application quit while clicking on the button. Now, we want that, when clicking on the button, the text is changed. More precisely, we want that the button can be checked, and that, when checked, it displays "checked", and when unchecked, it restores "Hello World".

QPushButton does not implement such a specific slot, so we have to implement it on our own. As stated previously, we have to add the Q_OBJECT macro.

class Window : public QWidget
{
 Q_OBJECT
public:
 explicit Window(QWidget *parent = 0);
private:
 QPushButton *m_button;
};

We also add our custom slot. Since we are trying to react from the button being checked, and since the corresponding signal is

void QPushButton::clicked(bool checked)

we might implement a slot that has this signature :

void Window::slotButtonClicked(bool checked);

Most of the time, by convention, we implement private and protected slots by prefixing them with "slot". Here, we are not interested in exposing this slot as a public function, we can make it private. The new header is then

window.h

#ifndef WINDOW_H
#define WINDOW_H

#include <QWidget>

class QPushButton;
class Window : public QWidget
{
 Q_OBJECT
public:
 explicit Window(QWidget *parent = 0);
private slots:
 void slotButtonClicked(bool checked);
private:
 QPushButton *m_button;
};

#endif // WINDOW_H

The implementation of this slot is

void Window::slotButtonClicked(bool checked)
{
 if (checked) {
 m_button->setText("Checked");
 } else {
 m_button->setText("Hello World");
 }
}

We need to make the button checkable, and establish the connection, we have to add this code in the constructor :

m_button->setCheckable(true);

connect(m_button, SIGNAL (clicked(bool)), this, SLOT (slotButtonClicked(bool)));

The resulting code is then

window.cpp

#include "window.h"

#include <QPushButton>

Window::Window(QWidget *parent) :
 QWidget(parent)
{
 // Set size of the window
 setFixedSize(100, 50);

// Create and position the button
 m_button = new QPushButton("Hello World", this);
 m_button->setGeometry(10, 10, 80, 30);
 m_button->setCheckable(true);

connect(m_button, SIGNAL (clicked(bool)), this, SLOT (slotButtonClicked(bool)));
}

void Window::slotButtonClicked(bool checked)
{
 if (checked) {
 m_button->setText("Checked");
 } else {
 m_button->setText("Hello World");
 }
}

And we should get this as a result

Custom slot

Emitting custom signals

Based on the previous example, we want to close the application if the button is clicked (checked or unchecked) 10 times. We first need to implement a counter that will count the number of clicks. These modifications implement it

class Window : public QWidget
{
 Q_OBJECT
public:
 explicit Window(QWidget *parent = 0);
private slots:
 void slotButtonClicked(bool checked);
private:
 int m_counter;
 QPushButton *m_button;
};

and

Window::Window(QWidget *parent) :
 QWidget(parent)
{
 // Set size of the window
 setFixedSize(100, 50);

// Create and position the button
 m_button = new QPushButton("Hello World", this);
 m_button->setGeometry(10, 10, 80, 30);
 m_button->setCheckable(true);

// Set the counter to 0
 m_counter = 0;

connect(m_button, SIGNAL (clicked(bool)), this, SLOT (slotButtonClicked(bool)));
}

void Window::slotButtonClicked(bool checked)
{
 if (checked) {
 m_button->setText("Checked");
 } else {
 m_button->setText("Hello World");
 }

m_counter '''';
}

Now, we have to create a custom signal that is used to notify other components, that the counter has reached 10. In order to declare a signal, we have to add a

signals

section in the header. We might also declare a signal with the following signature

void Window::counterReached()

The header class is then declared as followed

class Window : public QWidget
{
 Q_OBJECT
public:
 explicit Window(QWidget *parent = 0);
signals:
 void counterReached();
private slots:
 void slotButtonClicked(bool checked);
private:
 int m_counter;
 QPushButton *m_button;
};

Even if the signal is declared as a method, there is no need to implement it. The meta-object compiler is used to do this.

Now we need to emit the signal when the counter reaches 10. It is simply done in the slot

void Window::slotButtonClicked(bool checked)
{
 if (checked) {
 m_button->setText("Checked");
 } else {
 m_button->setText("Hello World");
 }

m_counter '''';
 if (m_counter == 10) {
 emit counterReached();
 }
}

We need to write the keyword emit to send the signal.

Connecting the newly created signal to the

quit

slot is done as usual

connect(this, SIGNAL (counterReached()), QApplication::instance(), SLOT (quit()));

The final code is

window.h

#ifndef WINDOW_H
#define WINDOW_H

#include <QWidget>

class QPushButton;
class Window : public QWidget
{
 Q_OBJECT
public:
 explicit Window(QWidget *parent = 0);
signals:
 void counterReached();
private slots:
 void slotButtonClicked(bool checked);
private:
 int m_counter;
 QPushButton *m_button;
};

#endif // WINDOW_H

window.cpp

#include "window.h"

#include <QPushButton>
#include <QApplication>

Window::Window(QWidget *parent) :
 QWidget(parent)
{
 // Set size of the window
 setFixedSize(100, 50);

// Create and position the button
 m_button = new QPushButton("Hello World", this);
 m_button->setGeometry(10, 10, 80, 30);
 m_button->setCheckable(true);

// Set the counter to 0
 m_counter = 0;

connect(m_button, SIGNAL (clicked(bool)), this, SLOT (slotButtonClicked(bool)));
 connect(this, SIGNAL (counterReached()), QApplication::instance(), SLOT (quit()));
}

void Window::slotButtonClicked(bool checked)
{
 if (checked) {
 m_button->setText("Checked");
 } else {
 m_button->setText("Hello World");
 }

m_counter '''';
 if (m_counter == 10) {
 emit counterReached();
 }
}

And you can try and check that after clicking the button ten times, the application will quit.

Troubleshooting

While compiling your program, especially when you are adding the macro Q_OBJECT, you might have this compilation error.

main.cpp:(.text._ZN6WindowD2Ev[_ZN6WindowD5Ev]+0x3): undefined reference to `vtable for Window'

This is because of the meta-object compiler not being run on a class that should have meta-object. You should rerun qmake, by doing Build > Run qmake.