QT基础

目录

学习内容:

1. 常用类

1.1 信息调试类QDebug

1.2 按钮类(QPushButton)

1.3 行编辑器类(QLineEdit) 

1.4 标签类(QLabel)

 2. 对象树模型

2.1 对象树模型的概述

2.2 使用C++证明对象树模型的内部实现

3. 信号与槽机制 

3.1 信号与槽机制的概述

3.2 手动连接信号与槽

3.3 手动定义信号并发射

3.4 信号函数和槽函数之间的关系

 3.5 信号与槽连接的总结

3.6 使用信号与槽完成两个界面跳转


学习内容:

1. 常用类

1.1 信息调试类QDebug

        1> 该类中使用qDebug()来完成信息的调试功能

        2> 使用方式:

                qDebug("%d", 520); //类似于printf

                qDebug()<<"hello";//类似于cout

1.2 按钮类(QPushButton)

        1> 该类提供了一个普通按钮

        2> 该类的常用函数

  //1、使用无参构造,构造一个按钮
    //QPushButton btn1(this);          //不能在栈区申请,否则会被刷新掉
    QPushButton *btn1 = new QPushButton;     //调用无参构造,构造一个按钮
    //btn1->show();             //如果没有指定父组件,那么该组件就是游离的
    btn1->setParent(this);        //将自定义的界面当作按钮类的父组件
    btn1->setText("支付");           //设置按钮文本内容
    qDebug() << "btn1.size = "<<btn1->size();      //获取按钮尺寸
    btn1->resize(80,40);              //设置按钮大小
    btn1->move(100,200);              //移动按钮位置
    btn1->setStyleSheet("background-color:skyblue; border-radius:10;");    //设置样式表
    btn1->setIcon(QIcon("D:\\24061QT\\day1\\icon\\weixinzhifu.png"));       //设置按钮图标


    //2、构造按钮时,直接指定父组件
    QPushButton *btn2 = new QPushButton(this);
    btn2->setText("取消");
    btn2->move(btn1->x()+btn1->width()+2, btn1->y());       //相对于btn1的位置进行定位
    btn2->resize(btn1->size());            //设置按钮尺寸
    btn2->setEnabled(false);               //设置按钮不可用


    //3、构造按钮时,指定父组件并且设置文本内容
    QPushButton *btn3 = new QPushButton("确定", this);
    btn3->resize(btn1->size());      //重置大小
    btn3->move(btn2->x()+btn2->width()+2, btn2->y());


    //4、构造按钮时,指定父组件并设置文本内容,并设置按钮图标
    QPushButton *btn4 = new QPushButton(QIcon("D:\\24061QT\\day1\\icon\\wode.png"), "注册", this);
    btn4->resize(btn1->size());
    btn4->move(btn3->x()+btn3->width(), btn3->y());

1.3 行编辑器类(QLineEdit) 

        1> 该类提供了一个行编辑器,输入文本只在一行内展示

        2> 所需头文件:#include

        3> 常用函数:

  QLineEdit *edit1 = new QLineEdit;
    edit1->setParent(this);          //指定父组件
    edit1->resize(300, 30);          //重新设置大小
    edit1->move(lab1->x()+lab1->width()+2, lab1->y());    //移动位置


    //2、使用有参构造完成构造一个行编辑器
    QLineEdit  *edit2 = new QLineEdit("密码", this);
    edit2->resize(300, 30);          //重新设置大小
    edit2->move(lab2->x()+lab1->width()+2, lab2->y());    //移动位置
    edit2->clear();                       //清空内容
    edit2->setPlaceholderText("密码");            //设置占位文本
    edit2->setEchoMode(QLineEdit::Password);        //设置回显模式

1.4 标签类(QLabel)

        1> 该类提供的能够展示文本内容或者图片的容器

        2> 所需头文件:#include

        3> 常用函数

   //1、使用无参构造完成构造一个标签
    QLabel *lab1 = new QLabel;
    lab1->setParent(this);          //设置父组件
    lab1->setText("账号:");          //设置文本内容
    lab1->move(btn1->x(), btn1->y()-90);    //设置坐标


    //2、使用有参构造完成构造一个标签
    QLabel *lab2 = new QLabel("密码:", this);
    lab2->move(lab1->x(), lab1->y()+40);


    //3、调用有有参构造,指定父组件,构造一个lab
    QLabel *lab3 = new QLabel(this);
    lab3->resize(500, 100);
    lab3->setStyleSheet("background-color:pink;");       //设置样式表


    //给标签设置动图
    //创建一个movie对象
    QMovie *movie = new QMovie("D:\\24061QT\\day1\\pictrue\\zz.gif");
    //将动图对象放入到标签中
    lab3->setMovie(movie);
    //让动图动起来
    movie->start();


    //让标签内容自适应大小
    lab3->setScaledContents(true);


    //给标签设置静态图
    lab1->resize(30,30);
    lab1->setPixmap(QPixmap("D:\\24061QT\\day1\\pictrue\\userName.jpg"));
    lab1->setScaledContents(true);
    lab2->resize(30,30);
    lab2->setPixmap(QPixmap("D:\\24061QT\\day1\\pictrue\\passwd.jpg"));
    lab2->setScaledContents(true);

 2. 对象树模型

2.1 对象树模型的概述

1> 在对象树模型中,子组件构造时,需要指定父组件而存在

2> 子组件的生命周期由父组件进行管理

3> 当父组件展示时,会将子组件一并展示,当父组件释放空间时,会将加载在该组件上的所有子组件的空间全部释放

4> 对象树模型保证了,各个组件的内存不会泄露

5> 在栈区申请的组件,程序结束后,由系统自动回收,在堆区申请的组件,结束后,由其父组件进行回收资源

6> 父组件和子组件要用于共同的祖先类,实现的理论基础为多态

7> 每一个组件中都会拥有一个父组件指针和一个子组件链表

2.2 使用C++证明对象树模型的内部实现

#include <iostream>
#include<list>
using namespace std;
class Obj;


typedef list<Obj *> childList;


class Obj
{
public:
    Obj(Obj* parent = nullptr)
    {
        if(parent != nullptr)
        {
            parent->child.push_back(this);
        }
    }


    virtual ~Obj()
    {
        for(auto ptr = this->child.begin(); ptr!=this->child.end(); ptr++)
        {
            cout<<"析构子组件"<<endl;
            delete *ptr;


        }
    }


    childList &childl()
    {
        return child;
    }


public:
    childList child;
};




class A:public Obj
{
public:
    A(Obj *parent = nullptr):Obj(parent) {
        if(parent != nullptr)
        {
            this->parent = parent;
            parent->child.push_back(this);
        }
        cout<<"A::构造函数"<<endl;
    }
    ~A(){
        if(parent != nullptr)
        {
            parent->child.remove(this);
            cout<<"父类对象移除自己"<<endl;
        }
        cout<<"A::析构函数"<<endl;
    }


    Obj *parent = nullptr;
};


class B:public Obj
{
public:
    B(Obj *parent = nullptr):Obj(parent) {
        if(parent != nullptr)
        {
            this->parent  = parent;
            parent->child.push_back(this);
        }
        cout<<"B::构造函数"<<endl;
    }
    ~B(){
        if(parent != nullptr)
        {


            parent->child.remove(this);
            cout<<"父类对象移除自己"<<endl;
        }
        cout<<"B::析构函数"<<endl;
    }


     Obj *parent = nullptr;
};


int main()
{
    A a1;
    B * b1 = new B(&a1);
    //delete b1;
    cout<<"********************************"<<endl;

    return 0;
}

3. 信号与槽机制 

        信号与槽机制,是qt能够在所有编程语言中,傲立不倒的重要机制,发生在两个组件之间,相当于两个组件的通信

3.1 信号与槽机制的概述

1> 原理

一个组件用于发射信号,与之绑定的组件收到信号后,会立刻做出相应

2> 信号:

所谓信号,就是信号函数,定义在类的signals权限下,是一个不完整的函数,只有函数声明,没有函数定义。返回值类型为void

信号函数不能当作普通函数一样被调用,只能被发射出去。

3> 槽:

所谓槽,就是槽函数,定义在类的slots权限,是一个完整的函数,既有函数声明,也有函数定义,返回值类型为void

槽函数可以当作普通函数一样被调用,但是普通函数不能当作槽函数接收信号

4> 包含信号与槽的类格式如下:

class Widget : public QWidget
{
    Q_OBJECT        //信号与槽的宏对象,有了该宏,信号与槽才能正常使用


public:
    Widget(QWidget *parent = nullptr);
    ~Widget();


signals:
    void my_signal();          //信号函数的定义


public slots:
    void my_slot();           //自定义槽函数的声明




private:
    Ui::Widget *ui;
};

5> 系统提供的组件,一般都默认自带指定的信号函数和槽函数,也可以自定义信号函数和槽函数

3.2 手动连接信号与槽

1> 使用qt4版本的连接函数:该连接函数是不友好的连接,即使函数名写错,也不会报错

[static] QMetaObject::Connection             //函数返回值类型,是一个连接,是静态成员函数
    QObject::connect(                        //函数名
        const QObject *sender,               //参数1:信号的发送者组件的地址
        const char *signal,                 //要发射的信号:需要的是const char *的字符串,需要使用宏函数来将函数名转变成字符串SIGNAL()
        const QObject *receiver,             //信号接收者组件的地址
        const char *method)                //信号的接收者对应的槽函数:需要使用宏函数来转变  SLOT()
举个例子:
  QLabel *label = new QLabel;
  QScrollBar *scrollBar = new QScrollBar;
  QObject::connect(scrollBar, SIGNAL(valueChanged(int)),
                   label,  SLOT(setNum(int)));

2> 使用qt5版本的连接函数 

[static] QMetaObject::Connection     //函数返回值类型,是一个连接,是静态成员函数
    QObject::connect(                 //函数名
        const QObject *sender,        //信号发射者组件的地址
        PointerToMemberFunction signal,     //要发射的信号:函数指针,要求传递函数的地址
        const QObject *receiver,       //信号接收者组件的地址
        PointerToMemberFunction method)    //要执行的功能:函数指针
举个例子:
  QLabel *label = new QLabel;
  QLineEdit *lineEdit = new QLineEdit;
  QObject::connect(lineEdit, &QLineEdit::textChanged,
                   label,  &QLabel::setText);

3> C++11后的连接函数 

[static] QMetaObject::Connection                    函数返回值类型,是一个连接,是静态成员函数
    QObject::connect(                                //函数名
        const QObject *sender,                       //信号发送者组件的地址
        PointerToMemberFunction signal,              //要发送的信号:函数指针
        Functor functor)                            //要执行的逻辑,可以时全局函数、仿函数、lambda表达式
举个例子1:全局函数作为槽函数
  void someFunction();
  QPushButton *button = new QPushButton;
  QObject::connect(button, &QPushButton::clicked, someFunction);
  
  举个例子2:lambda表达式作为槽函数
    QByteArray page = ...;
  QTcpSocket *socket = new QTcpSocket;
  socket->connectToHost("qt-project.org", 80);
  QObject::connect(socket, &QTcpSocket::connected, [=] () {
          socket->write("GET " + page + "\r\n");
      });

3.3 手动定义信号并发射

1> 需要在类的signal权限下定义信号,返回值为void,参数取决于需求而定,不需要实现函数体内容

2> 在程序的适当位置,使用关键字 emit 信号名(实参);进行发射信号

3> 当信号发射后,与该信号关联的槽函数就会自动执行

3.4 信号函数和槽函数之间的关系

 1、信号函数和槽函数进行链接时,一般要求信号函数和槽函数的参数保持一致
        connect(信号发送者, SIGNAL(signalFun()),信号接收者, SLOT(slotFun()));     //Ok
        connect(信号发送者, SIGNAL(signalFun(int)),信号接收者, SLOT(slotFun(int)));     //Ok
        connect(信号发送者, SIGNAL(signalFun(int, char)),信号接收者, SLOT(slotFun(int, char)));     //Ok
        connect(信号发送者, SIGNAL(signalFun(Qstring, int)),信号接收者, SLOT(slotFun(int, QString)));     //False
        connect(信号发送者, SIGNAL(signalFun(int)),信号接收者, SLOT(slotFun(QString)));     //False
    2、当信号函数的参数大于槽函数的参数时
        connect(信号发送者, SIGNAL(signalFun(int, char)),信号接收者, SLOT(slotFun()));     //Ok
        connect(信号发送者, SIGNAL(signalFun(int, char)),信号接收者, SLOT(slotFun(int)));     //Ok
        connect(信号发送者, SIGNAL(signalFun(int, QString)),信号接收者, SLOT(slotFun(QString)));     //False
    3、当信号函数的参数小于槽函数的参数时
        connect(信号发送者, SIGNAL(signalFun(int)),信号接收者, SLOT(slotFun(int, char)));     //False
        connect(信号发送者, SIGNAL(signalFun(int)),信号接收者, SLOT(slotFun(int, char=0)));     //Ok   可以使用qt4版本传,但是不支持了

#include "widget.h"
#include "ui_widget.h"
#include<QDebug>


Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);
    //将信号函数1和槽函数1进行绑定
    connect(this, &Widget::mySignal1, this, &Widget::mySlot1);


    //信号函数的参数大于槽函数的参数:信号函数传来的数据槽函数可以不接
    connect(this, &Widget::mySignal2, this, &Widget::mySlot1);


    //将带参信号与带参槽进行连接
    connect(this, &Widget::mySignal2, this, &Widget::mySlot2);
    //connect(this, &Widget::mySignal2, this, &Widget::mySlot3);
    //connect(this, SIGNAL(mySignal2(int)), this, SLOT(mySlot3(int, QString)));


    //将带参信号与带参槽连接
    connect(this, &Widget::mySignal3, this, &Widget::mySlot3);
}


Widget::~Widget()
{
    delete ui;
}


//槽函数1的定义
void Widget::mySlot1()
{
    qDebug() << "触发了槽函数1的相关功能";
}
//槽函数2的定义
void Widget::mySlot2(int num)
{
    qDebug()<<"您触发了槽函数2 num = "<<num;
}
//槽函数3的定义
void Widget::mySlot3(int num, QString str)
{
    qDebug()<<"您触发了槽函数3 num = "<<num<<"   str = "<<str;
}


//按钮1对应的槽函数
void Widget::on_btn1_clicked()
{
    //手动发射信号1
    //emit mySignal1();
    //手动发射信号2
    emit mySignal2(520);
    //手动发射信号3
    emit mySignal3(520, "1314");
}

 3.5 信号与槽连接的总结

        1> 一个信号可以连接到多个槽函数中

        2> 多个信号可以连接到同一个槽函数中,当连接的任意一个信号被发射出来后,槽函数就立即执行

        3> 一个信号函数也可以连接到另一个信号函数上,表示当前面的信号被发射 后,后面的信号紧跟着发射出去

#include "widget.h"
#include "ui_widget.h"
#include<QDebug>


Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);
    //将信号函数1和槽函数1进行绑定
    connect(this, &Widget::mySignal1, this, &Widget::mySlot1);


    //信号函数的参数大于槽函数的参数:信号函数传来的数据槽函数可以不接
    connect(this, &Widget::mySignal2, this, &Widget::mySlot1);


    //将带参信号与带参槽进行连接
    connect(this, &Widget::mySignal2, this, &Widget::mySlot2);
    //connect(this, &Widget::mySignal2, this, &Widget::mySlot3);
    //connect(this, SIGNAL(mySignal2(int)), this, SLOT(mySlot3(int, QString)));


    //将带参信号与带参槽连接
    connect(this, &Widget::mySignal3, this, &Widget::mySlot3);


    //将一个信号绑定到另一信号上
    connect(ui->btn1, &QPushButton::clicked, this, &Widget::mySignal1);


    connect(ui->btn1, &QPushButton::clicked, this, &Widget::mySlot1);
}


Widget::~Widget()
{
    delete ui;
}


//槽函数1的定义
void Widget::mySlot1()
{
    qDebug() << "触发了槽函数1的相关功能";
}
//槽函数2的定义
void Widget::mySlot2(int num)
{
    qDebug()<<"您触发了槽函数2 num = "<<num;
}
//槽函数3的定义
void Widget::mySlot3(int num, QString str)
{
    qDebug()<<"您触发了槽函数3 num = "<<num<<"   str = "<<str;
}


//按钮1对应的槽函数
void Widget::on_btn1_clicked()
{
    //手动发射信号1
    //emit mySignal1();
    //手动发射信号2
    //emit mySignal2(520);
    //手动发射信号3
    //emit mySignal3(520, "1314");
}

3.6 使用信号与槽完成两个界面跳转

1> 准备两个界面

2> 在第一个界面定义跳转的槽函数,并且在相应位置,发射该信号

3> 在第二个界面定义槽函数,接收信号后,展示界面

4> 在主函数中实例化第二个界面,并且连接两个界面的信号与槽

  • 48
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值