Specifying the parent object

When no parent object is assigned to a control object, the Windows are independent of each other. To include a button in a window, you need to assign a parent object to the button control.

#include <QApplication>
#include <QWidget>    // Window control header file
#include <QPushButton>    // Button control header file
int main(int argc,char **argv){
    QApplication app(argc,argv);
    QWidget w;
    QPushButton b;
    
    w.setWindowTitle("helloqt");    // Set the window title
    w.show(a);// The window is artificially displayed
    
    b.setText("I am the button.");  // Set the button content
    b.show(a);// The button is artificially displayed
    
    app.exec(a);return 0;
}
Copy the code

There are two ways to specify the parent object: ①setParent() ② pass arguments through the constructor

If the parent object is specified, only the parent object is displayed. the child object is displayed automatically because it is contained in the parent object

Note: The parent control must call show() after the child control is defined and set to display the child control, otherwise the child control will not display.

Call setParent() to specify the parent object
#include <QApplication>
#include <QWidget>
#include <QPushButton>
int main(int argc,char **argv){
    QApplication app(argc,argv);
    QWidget w;
    QPushButton b;
 
    w.setWindowTitle("helloqt");    // Set the window title
    // w.how () is written here and the child control is not displayed!!
 
    b.setText("I am the button.");  // Set the button content
    b.setParent(&w);    // The argument type is a pointer, so it takes an address
    b.move(100.100);
 
    w.show(a);// The window is artificially displayed
 
    app.exec(a);return 0;
}
Copy the code
// Use the constructor to specify the parent object
#include <QApplication>
#include <QWidget>
#include <QPushButton>
int main(int argc,char **argv){
    QApplication app(argc,argv);
    QWidget w;
 
    w.setWindowTitle("helloqt");    // Set the window title
    // w.how () is written here and the child control is not displayed!!
 
    QPushButton b1(&w);
    b1.setText("Constructor specifies parent object");
 
    w.show(a);// The window is artificially displayed
 
    app.exec(a);return 0;
}
Copy the code

Standard signals and slots (actions and processing functions)

In order not to make the code in main. CPP too verbose, and also to better design the custom control to meet our needs, the definition of the child control in the parent control can be written in the parent control corresponding header file, in main. CPP to import the header file.

Why isn’t the definition of the child control written in the parent control’s constructor? Because in main. CPP, the program is executed sequentially, the child controls defined in the parent control’s constructor no longer exist after execution. The child controls are not displayed when the parent controls call the show() method. Operations on controls can be written in constructors.

The following is the code that defines and manipulates the child control directly in the parent control constructor. The result is to display only the parent control, not the child control.

// The parent control constructor mainWidget.cpp
#include "mainwidget.h"
#include <QPushButton>
MainWidget::MainWidget(QWidget *parent)
    : QWidget(parent)
{
    QPushButton b;
    b.setParent(this);
    b.setText("Define child controls in constructor");
}
 
MainWidget::~MainWidget() {}Copy the code

Note: After executing the parent control’s constructor, the child controls defined in the parent control’s constructor no longer exist, so no child controls are displayed in the parent control.

Declare the child control in the parent control corresponding header file, in the parent control constructor for the child control specific operations. The result is that the parent control contains two child controls.

// The parent control's header file mainWidget.h
#ifndef MAINWIDGET_H
#define MAINWIDGET_H
 
#include <QWidget>
#include <QPushButton>
class MainWidget : public QWidget
{
    Q_OBJECT
 
public:
    MainWidget(QWidget *parent = 0);
    ~MainWidget(a);private:
    QPushButton b1;
    QPushButton *b2;
};
 
#endif // MAINWIDGET_H= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =// The parent control's constructor mainWidget.cpp
#include "mainwidget.h"
#include <QPushButton>
MainWidget::MainWidget(QWidget *parent)
    : QWidget(parent)
{
    // The b1 and b2 buttons are already defined in the mainwidget.h header file
    b1.setParent(this);
    b1.setText("I'm button one.");
    b1.move(100.100);
 
    b2=new QPushButton(this);    // Apply for space and specify the parent element using the constructor
    b2->setText("This is button two.");
}
 
MainWidget::~MainWidget() {}Copy the code

Note: since b2 is defined as a pointer type, you must apply for a new space with the new keyword before using it. Not when calling a method. Use – > instead.

Qt uses a connect() method to establish a connection between parent controls and child controls. Usage is:

connect(sender, SIGNAL(signal), receiver, SLOT(slot));

Where, the sender is the SIGNAL sender, the SIGNAL(SIGNAL) is the SIGNAL to process, the receiver is the SIGNAL receiver, and the SLOT(SLOT) is the SIGNAL handler

#include "mainwidget.h"
#include <QPushButton>
MainWidget::MainWidget(QWidget *parent)
    : QWidget(parent)
{
/* QPushButton b; b.setParent(this); B.settext (" define child controls in constructor "); * /
    // The b1 and b2 buttons are already defined in the mainwidget.h header file
    b1.setParent(this);
    b1.setText("Click on me to close");
    b1.move(100.100);
    b2=new QPushButton(this);
    b2->setText("This is button two.");
 
    connect(&b1,&QPushButton::pressed,this,&MainWidget::close);
    /* &b1: signal sender, pointer type &QPushButton:: Pressed: process signal, & The sender's class name :: signal name this: Signal receiver &MainWidget::close: slot function, signal handler, & the receiver's class name :: slot function name */
}
 
MainWidget::~MainWidget() {}Copy the code

Note:

What are the processing signals? Hover over the header file, press F1, and look for Signals in Content on the right side of the help document. If not, it’s probably in the base class from which the current class inherits.

 

As a result, QPushButton signals can be clicked, pressed, released, and toggled.

When processing signals and slot functions as parameters to connect(), specify the sender class name :: signal name and receiver class name :: slot name, along with the fetch address.

Custom slot function

If the built-in slot function is not enough to achieve the desired effect, we can also customize the slot function.

So what functions can be slot functions? Arbitrary member functions, ordinary global functions, static functions

The use of a custom slot function is the same as that of a normal function. The slot function needs to be consistent with the signal (parameter, return value). Since the signal has no return value, the slot function does not have either.

Slot functions are generally regarded as member functions of the receiver’s class, so they are declared in the header file of the receiver’s class and implemented in the constructor of the receiver’s class. In the help document, the parameters and return values of the signal are the same as those of the corresponding slot function.

// MainWidget.h window header file
#ifndef MAINWIDGET_H
#define MAINWIDGET_H
 
#include <QWidget>
#include <QPushButton>
class MainWidget : public QWidget
{
    Q_OBJECT
 
public:
    MainWidget(QWidget *parent = 0);
    ~MainWidget(a);void MySlot(a);    // Declare custom slot functions in the form of member functions
private:
    QPushButton b1;
    QPushButton *b2;
};
 
#endif // MAINWIDGET_H= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =// MainWidget. CPP window constructor
#include "mainwidget.h"
#include <QPushButton>
MainWidget::MainWidget(QWidget *parent)
    : QWidget(parent)
{
/* QPushButton b; b.setParent(this); B.settext (" define child controls in constructor "); * /
    // The b1 and b2 buttons are already defined in the mainwidget.h header file
    b1.setParent(this);
    b1.setText("Click on me to close");
    b1.move(100.100);
    b2=new QPushButton(this);
    b2->setText("This is button two.");
 
    connect(&b1,&QPushButton::pressed,this,&MainWidget::close);
    /* &b1: signal sender, pointer type &QPushButton:: Pressed: processing the signal, & The sender's class name :: signal name this: Signal receiver &MainWidget::close: slot function, signal handler & the received class name :: slot function name */
    connect(b2,&QPushButton::released,this,&MainWidget::MySlot);
    connect(b2,&QPushButton::released,&b1,&QPushButton::hide);
    /* Signal: SMS slot function: receive SMS phone */
}
void MainWidget::MySlot(a){
    b2->setText("Member functions of slot functions");
}
MainWidget::~MainWidget() {}Copy the code

Note:

B2 is defined as a pointer type in the header file, so it does not need to be used as a parameter.

The implementation of the slot function is written in the constructor.

Experiment: to achieve two independent Windows

Now we want to implement two independent Windows, click the button in the main window, the main window hide, show the secondary window, click the button in the secondary window, the secondary window hide, show the main window.

To create the side window, create a new C++ Class file under the project. The Base Class is QWidget, and the Class Name is assumed to be SubWidget.

//subwidget.h subwindow header file
#ifndef SUBWIDGET_H
#define SUBWIDGET_H
 
#include <QWidget>
#include <QPushButton>
class SubWidget : public QWidget
{
    Q_OBJECT
public:
    explicit SubWidget(QWidget *parent = 0);
 
signals:
 
public slots:
 
private:
    QPushButton b;
 
};
 
#endif // SUBWIDGET_H= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =//subwidget. CPP subwindow constructor
#include "subwidget.h"
 
SubWidget::SubWidget(QWidget *parent) : QWidget(parent)
{
    this->setWindowTitle("Little brother");
    b.setText("Click to switch to main window");
    b.setParent(this);
}
Copy the code

Only the main window is displayed. Why?

Because in main.cpp, only the mainWidget is displayed, and the subwidget is independent of the MainWidget, it is not displayed.

In addition, because the parent object is then specified in another window, the parent-child relationship cannot be specified to keep the two Windows independent. Instead, you should control whether the current window is displayed through another window.

So we introduce the secondary window’s header file into the main window’s header file, creating an object for the secondary window. Make the secondary window object a private member in the main window constructor. To make the secondary window visible, simply call the show() method on the secondary window object in the constructor of the main window.

// mainWidget.h Main window header file
#ifndef MAINWIDGET_H
#define MAINWIDGET_H
 
#include <QWidget>
#include <QPushButton>
#include "subwidget.h"    // Introduce the secondary window header file.
class MainWidget : public QWidget
{
    Q_OBJECT
 
public:
    MainWidget(QWidget *parent = 0);
    ~MainWidget(a);void MySlot(a);
private:
    QPushButton b1;
    QPushButton *b2;
    QPushButton b3;
    SubWidget w;    // Create a secondary window object as a private member of the main window
};
 
#endif // MAINWIDGET_H= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =// mainWidget. CPP Main window constructor
#include "mainwidget.h"
#include <QPushButton>
MainWidget::MainWidget(QWidget *parent)
    : QWidget(parent)
{
/* QPushButton b; b.setParent(this); B.settext (" define child controls in constructor "); * /
    // The b1 and b2 buttons are already defined in the mainwidget.h header file
    b1.setParent(this);
    b1.setText("Click on me to close");
    b1.move(100.100);
    b2=new QPushButton(this);
    b2->setText("This is button two.");
 
    connect(&b1,&QPushButton::pressed,this,&MainWidget::close);
    /* &b1: signal sender, pointer type &QPushButton:: Pressed: processing the signal, & The sender's class name :: signal name this: Signal receiver &MainWidget::close: slot function, signal handler & the received class name :: slot function name */
    connect(b2,&QPushButton::released,this,&MainWidget::MySlot);
    connect(b2,&QPushButton::released,&b1,&QPushButton::hide);
    /* Signal: SMS slot function: receive SMS phone */
    this->setWindowTitle("The boss");
    b3.setText("Click to switch to side window");
    b3.setParent(this);
    b3.move(50.50);
    w.show(a);// Controls the display of secondary Windows in the constructor of the main window
}
void MainWidget::MySlot(a){
    b2->setText("Member functions of slot functions");
}
MainWidget::~MainWidget() {}Copy the code

Because child and child Windows do not specify the parent relationship with setParent, they are independent of each other.

In the main window through the button to control their own hide their secondary window display is easy to achieve, but in the secondary window how to achieve their own hide and the main window display through the button?

Since the secondary window does not have permission to process the main window, it sends a signal for the main window to process itself. The secondary window sends a signal that the main window receives and decides what to do with.

In the header file of the side window, declare some signals, which must be declared using the signals keyword.

The use of the signal is to add the emit keyword to the function call. Such as emit mySignal ();

// mainWidget.h Main window header file
#ifndef MAINWIDGET_H
#define MAINWIDGET_H
 
#include <QWidget>
#include <QPushButton>
#include "subwidget.h"
class MainWidget : public QWidget
{
    Q_OBJECT
 
public:
    MainWidget(QWidget *parent = 0);
    ~MainWidget(a);void MySlot(a);
    void hideBoss(a);
    void hideBro(a);
private:
    QPushButton b1;
    QPushButton *b2;
    QPushButton b3;
    SubWidget w;
};
 
#endif // MAINWIDGET_H= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =// mainWidget. CPP Main window constructor
#include "mainwidget.h"
#include <QPushButton>
MainWidget::MainWidget(QWidget *parent)
    : QWidget(parent)
{
/* QPushButton b; b.setParent(this); B.settext (" define child controls in constructor "); * /
    // The b1 and b2 buttons are already defined in the mainwidget.h header file
    b1.setParent(this);
    b1.setText("Click on me to close");
    b1.move(100.100);
    b2=new QPushButton(this);
    b2->setText("This is button two.");
    resize(400.300);
 
    connect(&b1,&QPushButton::pressed,this,&MainWidget::close);
    /* &b1: signal sender, pointer type &QPushButton:: Pressed: processing the signal, & The sender's class name :: signal name this: Signal receiver &MainWidget::close: slot function, signal handler & the received class name :: slot function name */
    connect(b2,&QPushButton::released,this,&MainWidget::MySlot);
    connect(b2,&QPushButton::released,&b1,&QPushButton::hide);
    /* Signal: SMS slot function: receive SMS phone */
    this->setWindowTitle("The boss");
    b3.setText("Click to switch to side window");
    b3.setParent(this);
    b3.move(50.50);
  // w.show();
 
    connect(&b3,&QPushButton::released,this,&MainWidget::hideBoss);
    connect(&w,&SubWidget::mySignal,this,&MainWidget::hideBro);    // The main window receives the mySignal signal from the secondary window
}
void MainWidget::MySlot(a){
    b2->setText("Member functions of slot functions");
}
void MainWidget::hideBoss(a){
    this->hide(a); w.show(a); }void MainWidget::hideBro(a){
    show(a); w.hide(a); } MainWidget::~MainWidget() {} = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =//subwidget.h subwindow header file
#ifndef SUBWIDGET_H
#define SUBWIDGET_H
 
#include <QWidget>
#include <QPushButton>
class SubWidget : public QWidget
{
    Q_OBJECT
public:
    explicit SubWidget(QWidget *parent = 0);
    void sendSlot(a);    // This is a constant function
 
signals:
    Emit mySignal(); emit mySignal(); emit mySignal(); * /
    void mySignal(a);    // This is the signal
 
public slots:
 
private:
    QPushButton b;
 
};
 
#endif // SUBWIDGET_H= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =//subwidget. CPP subwindow constructor
#include "subwidget.h"
 
SubWidget::SubWidget(QWidget *parent) : QWidget(parent)
{
    this->setWindowTitle("Little brother");
    b.setText("Click to switch to main window");
    b.setParent(this);
    resize(400.300);
    connect(&b,&QPushButton::released,this,&SubWidget::sendSlot);
}
void SubWidget::sendSlot(a)
{
    emit mySignal(a);
}
 
Copy the code

As you can see from the above code, in order to implement two independent Windows, you cannot specify a parent-child relationship for the two Windows, but you need to implement mutual control between the two Windows. The control of the secondary window is as simple as making the secondary window a private member in its constructor, calling connect(), and using slot functions that are declared in a header file and implemented in the constructor. The secondary window does not have permission to operate on the main window, so signals are needed. For the side window, call connect(), using the slot function to send a signal. At the same time, connect() is called in the constructor of the main window to receive signals sent by the secondary window and operate on the main window using slot functions. This indirectly realizes the secondary window to the main window control.

Effect:

Execute the project and the results are as follows

Click “I am button 2” and the effect is as follows

Click “Click to switch to the side window” button, the effect is as follows

Note: When running other people’s projects in Qt, first delete the project directory. Pro. user file, otherwise the project compiler path is set by others, and the path is often inconsistent with the native path, the compilation may not be successful.

Signal overload

Signals can be overloaded (with the same name but different parameters). The signal is passing parameters to the slot function, so the corresponding parameters in the slot function should be of the same type as the parameter type of the signal.

//subwidget.h
#ifndef SUBWIDGET_H
#define SUBWIDGET_H
 
#include <QWidget>
#include <QPushButton>
class SubWidget : public QWidget
{
    Q_OBJECT
public:
    explicit SubWidget(QWidget *parent = 0);
    void sendSlot(a);    // This is a constant function
 
signals:
    Emit mySignal(); emit mySignal(); emit mySignal(); * /
    void mySignal(a);    // This is the signal
    void mySignal(int,QString);    // Signal declaration with parameters
 
public slots:
 
private:
    QPushButton b;
 
};
 
#endif // SUBWIDGET_H= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =//subwidget.cpp
#include "subwidget.h"
 
SubWidget::SubWidget(QWidget *parent) : QWidget(parent)
{
    this->setWindowTitle("Little brother");
    b.setText("Click to switch to main window");
    b.setParent(this);
    resize(400.300);
    connect(&b,&QPushButton::released,this,&SubWidget::sendSlot);
}
void SubWidget::sendSlot(a)
{
    emit mySignal(a);
    emit mySignal(250."Ha ha ha."); } = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =//mainwidget.h
#ifndef MAINWIDGET_H
#define MAINWIDGET_H
 
#include <QWidget>
#include <QPushButton>
#include "subwidget.h"
class MainWidget : public QWidget
{
    Q_OBJECT
 
public:
    MainWidget(QWidget *parent = 0);
    ~MainWidget(a);void MySlot(a);
    void hideBoss(a);
    void hideBro(a);
    void outPut(int,QString);   // Consistent with signal parameters
private:
    QPushButton b1;
    QPushButton *b2;
    QPushButton b3;
    SubWidget w;
};
 
#endif // MAINWIDGET_H= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =//mainwidget.cpp
#include "mainwidget.h"
#include <QPushButton>
#include <QDebug>   / / print
MainWidget::MainWidget(QWidget *parent)
    : QWidget(parent)
{
/* QPushButton b; b.setParent(this); B.settext (" define child controls in constructor "); * /
    // The b1 and b2 buttons are already defined in the mainwidget.h header file
    b1.setParent(this);
    b1.setText("Click on me to close");
    b1.move(100.100);
    b2=new QPushButton(this);
    b2->setText("This is button two.");
    resize(400.300);
 
    connect(&b1,&QPushButton::pressed,this,&MainWidget::close);
    /* &b1: signal sender, pointer type &QPushButton:: Pressed: processing the signal, & The sender's class name :: signal name this: Signal receiver &MainWidget::close: slot function, signal handler & the received class name :: slot function name */
    connect(b2,&QPushButton::released,this,&MainWidget::MySlot);
    connect(b2,&QPushButton::released,&b1,&QPushButton::hide);
    /* Signal: SMS slot function: receive SMS phone */
    this->setWindowTitle("The boss");
    b3.setText("Click to switch to side window");
    b3.setParent(this);
    b3.move(50.50);
  // w.show();
 
    connect(&b3,&QPushButton::released,this,&MainWidget::hideBoss);
    connect(&w,&SubWidget::mySignal,this,&MainWidget::hideBro);
    connect(&w,&SubWidget::mySignal,this,&MainWidget::outPut);
    // The above two signals have the same name, resulting in ambiguity
}
void MainWidget::MySlot(a){
    b2->setText("Member functions of slot functions");
}
void MainWidget::hideBoss(a){
    this->hide(a); w.show(a); }void MainWidget::hideBro(a){
    show(a); w.hide(a); }void MainWidget::outPut(int a,QString b){    // Implement the slot function with parameters
    qDebug()<<a<<b;    // the usage is similar to cout in c++
}
 
MainWidget::~MainWidget() {}Copy the code

When signals are overloaded, they are ambiguous, so function Pointers are needed.

This is equivalent to giving two functions of the same name different names.

void (SubWidget::*signalWithout)()=&SubWidget::mySignal;
connect(&w,signalWithout,this,&MainWidget::hideBro);
void (SubWidget::*signalWith)(int,QString)=&SubWidget::mySignal;
connect(&w,signalWith,this,&MainWidget::outPut);
Copy the code

Note: the function pointer must be preceded by scope. Since it is a pointer, the ampersand is not required as a connect parameter.

At this point, although the compilation has passed and the result is run, but the Chinese characters are presented in Unicode encoding, which needs to be converted into UTF-8 encoding with toUtf8().data().

Where toUtf8() converts a string to a byte array and data() converts a byte array to a char *.

void MainWidget::outPut(int a,QString b){
    qDebug()<<a<<b.toUtf8().data(a); }Copy the code

Let’s take a look at how Qt4 is to achieve signal connection.

The slots function used here must be manually decorated with the slots keyword in the header file.

//mainwidget.cpp
connect(&subWin,SIGNAL(mySignal(int,QString)),this.SLOT(outPut));
//mainwidget.h
public slots:
    void outPut(int,QString);
Copy the code

SIGNAL and SLOT are macros that convert the function name to a string so that no error checking is performed and the function name can still be compiled if it is incorrectly written.

The disadvantage of Qt5 is that a different function pointer needs to be used to receive signals when they are overloaded.

conclusion

※ When creating a project, you can choose from the following base classes: MainWindow, QWidget, QDialog. They are a window with a menu bar, a normal window, and a non-scalable dialog box respectively. Class ClassName:public BaseClass{… }. That is, the created class is a public descendant of the base class we have chosen.

※ There are two ways to specify a parent object: setParent() and constructor. Specifying a parent can be nested so that all you need to do is call show() on the parent control and the child controls will be displayed. Otherwise, the controls are independent of each other, and you need to manually call show() on all the controls you want to display.

※ Implement two independent Windows, not only can use the secondary window as a private member of the main window constructor, but also directly in the main. CPP file, respectively, import the main and secondary window header file, and declare a main and secondary window object, and then call the show() method on them.

※ Signals and slots are the interface for communication between Qt objects.