• QT DAY2


    (QT中记得修改时保存代码,否则有些资源会加载失败,被坑很多次了.....)

    一、加载资源文件

    对于图片等资源文件我们需要将其打包成文件夹,使用相对路径使得使用者能加载到对应路径文件

    之后选择QT--》资源文件

     之后添加前缀及添加对应文件

     二、信号与槽机制(重点)

    是QT中用来实现多个组件之间互相通信的机制

    2.1信号与槽

    信号:就是信号函数,是一个信号函数,定义在类体内signals权限下,是一个不完整的函数,只有声明没有定义,你不能直接调用它,只能通过emit关键字来触发

    槽:就是槽函数,定义在类体的slots权限下,是一个完整的函数,既有声明也有定义,可以被当做普通函数被使用

    槽声明了就得定义,但是信号不用,声明了不触发也可以,二者返回值一般都是void,参数可以自定义(参数的目的为了传信息)

    2.2信号与槽的连接

    ui界面下信号与槽的连接方式只能发射系统提供的信号,可使用系统提供的槽函数接收

    也可右键转到槽,选择信号,槽函数骡子自己书写 

    而连接函数分为多种形式

    • qt4版本的连接函数(该版本是不友好的连接,因为它即使错了也不会给你报错)
    1. [static] QMetaObject::Connection //返回值是一个连接,并且该函数是一个静态成员函数
    2. QObject::connect( //函数名
    3. const QObject *sender, //信号的发射者,是组件的指针
    4. const char *signal, //要发射的信号是一个C语言风格的字符串,将信号函数传递进来时,需要使用SIGNAL宏进行转换
    5. const QObject *receiver, //信号的接受者,是组件的指针
    6. onst char *method) //处理信号的槽函数,是C风格字符串,将槽函数传递进来时,需要使用SLOT宏进行转换
    7. 注意:信号函数必须是信号的发射者所在的类中有的信号函数,而槽函数也必须是信号的接受者中有的槽函数
    8. 举个例子:
    9. QLabel *label = new QLabel;
    10. QScrollBar *scrollBar = new QScrollBar;
    11. QObject::connect(scrollBar, SIGNAL(valueChanged(int)),
    12. label, SLOT(setNum(int)));

    qt5版本的连接函数

    1. [static] QMetaObject::Connection //返回值是一个连接,并且该函数是一个静态成员函数
    2. QObject::connect( //函数名
    3. const QObject *sender, //信号的发射者,是组件的指针
    4. PointerToMemberFunction signal, //信号函数的函数指针变量,直接填写函数名即可
    5. const QObject *receiver, //信号的接受者,是组件的指针
    6. PointerToMemberFunction method) //槽函数的函数指针变量,直接填写函数名即可
    7. 举个例子:
    8. QLabel *label = new QLabel;
    9. QLineEdit *lineEdit = new QLineEdit;
    10. QObject::connect(lineEdit, &QLineEdit::textChanged,
    11. label, &QLabel::setText);

    信号也可连接lambda表达式或外部函数

    1. [static] QMetaObject::Connection //返回值是一个连接,并且该函数是一个静态成员函数
    2. QObject::connect( //函数名
    3. const QObject *sender, //信号的发射者,是组件的指针
    4. PointerToMemberFunction signal, //信号函数的函数指针变量,直接填写函数名即可
    5. Functor functor) //处理信号的功能函数,可以是全局函数,也可以是lambda表达式
    6. 举个例子:
    7. void someFunction();
    8. QPushButton *button = new QPushButton;
    9. QObject::connect(button, &QPushButton::clicked, someFunction);
    10. Lambda 表达式作为槽函数:
    11. QByteArray page = ...;
    12. QTcpSocket *socket = new QTcpSocket;
    13. socket->connectToHost("qt-project.org", 80);
    14. QObject::connect(socket, &QTcpSocket::connected, [=] () {
    15. socket->write("GET " + page + "\r\n");
    16. });

    2.3断开连接

    断开信号与槽的连接时使用disconect

    参数可不变

    1. void Widget::on_btn6_clicked()
    2. {
    3. disconnect(btn3, SIGNAL(pressed()), ui->btn1, SLOT(hide()));
    4. disconnect(ui->btn4, &QPushButton::clicked, this, &Widget::my_slot);
    5. }

    2.3发射自定义信号

    使用emit 加自定义信号名即可发射,在与槽函数连接后,槽函数会立即响应

    2.4信号与槽的案例——语音播报

    先在初始配置文件中,添加TextToSpeech库

     头文件中记得加头文件,及定义一个播报指针

    1. #ifndef WIDGET_H
    2. #define WIDGET_H
    3. #include
    4. #include
    5. #include
    6. #include //文本转语音的头文件
    7. QT_BEGIN_NAMESPACE
    8. namespace Ui { class Widget; }
    9. QT_END_NAMESPACE
    10. class Widget : public QWidget
    11. {
    12. Q_OBJECT //信号与槽的元对象
    13. signals:
    14. void my_signal(); //自定义信号函数
    15. public slots:
    16. void my_slot(); //自定义的槽函数
    17. public:
    18. Widget(QWidget *parent = nullptr);
    19. ~Widget();
    20. private slots:
    21. void on_btn2_clicked();
    22. void on_btn6_clicked();
    23. private:
    24. Ui::Widget *ui;
    25. //自定义一个按钮
    26. QPushButton *btn3;
    27. //定义一个播报员指针
    28. QTextToSpeech *speecher;
    29. };
    30. #endif // WIDGET_H

    源文件

    1. #include "widget.h"
    2. #include "ui_widget.h"
    3. void fun()
    4. {
    5. qDebug()<<"我是过路的";
    6. }
    7. Widget::Widget(QWidget *parent)
    8. : QWidget(parent)
    9. , ui(new Ui::Widget)
    10. {
    11. ui->setupUi(this);
    12. //给播报员实例化空间
    13. speecher = new QTextToSpeech(this);
    14. //给btn3实例化空间
    15. this->btn3 = new QPushButton("按钮3", this);
    16. this->btn3->move(ui->btn2->x(), ui->btn2->y()+50);
    17. this->btn3->resize(ui->btn2->size());
    18. //使用qt4版本的连接,将按钮3发射的pressed信号与按钮1的槽函数进行连接
    19. connect(btn3, SIGNAL(pressed()), ui->btn1, SLOT(hide()));
    20. //参数1:信号的发射者,按钮3的指针
    21. //参数2:要发射的信号,是在按钮所在类中拥有的信号函数,需要使用SIGNAL宏函数进行转换
    22. //参数3:信号的接受者,ui界面上的按钮1指针
    23. //参数4:处理信号的槽函数,是信号接收者所在类中拥有的槽函数
    24. //注意:该链接方式是不友好的链接,原因是 即使宏函数中写错,编译器不报错,但是没有现象
    25. //使用qt5版本的链接,将ui界面上的btn4按钮发射的clicked信号,与当前界面的自定义的槽函数连接
    26. connect(ui->btn4, &QPushButton::clicked, this, &Widget::my_slot);
    27. //将ui界面上的按钮5,发射的clicked信号,连接到全局函数中
    28. connect(ui->btn5, &QPushButton::clicked, fun);
    29. //将ui界面上的按钮5发射的clicked信号连接到lambda表达式中
    30. connect(ui->btn5, &QPushButton::clicked, [&](){
    31. // qDebug()<<"我是路人乙";
    32. speecher->say("我是路人乙");
    33. });
    34. //将当前界面的my_signal信号连接到自定义的槽函数中
    35. connect(this, &Widget::my_signal, [&](){
    36. speecher->say("已经成功断开按钮3和按钮4的连接");
    37. });
    38. }
    39. Widget::~Widget()
    40. {
    41. delete ui;
    42. }
    43. //自定义槽函数的实现
    44. void Widget::my_slot()
    45. {
    46. static int num = 0;
    47. if(num%2)
    48. {
    49. ui->btn2->setEnabled(false);
    50. }else
    51. {
    52. ui->btn2->setEnabled(true);
    53. }
    54. num++;
    55. }
    56. //该函数就是按钮2的clicked信号对应的槽函数
    57. void Widget::on_btn2_clicked()
    58. {
    59. static int num = 0;
    60. if(num % 3 == 0)
    61. {
    62. ui->btn2->setStyleSheet("background-color:red;");
    63. }else if(num % 3 == 1)
    64. {
    65. ui->btn2->setStyleSheet("background-color:yellow;");
    66. }else
    67. {
    68. ui->btn2->setStyleSheet("background-color:green;");
    69. }
    70. num++;
    71. }
    72. //断开按钮对应的槽函数
    73. void Widget::on_btn6_clicked()
    74. {
    75. disconnect(btn3, SIGNAL(pressed()), ui->btn1, SLOT(hide()));
    76. disconnect(ui->btn4, &QPushButton::clicked, this, &Widget::my_slot);
    77. //发射自定义的信号
    78. emit my_signal();
    79. }

    练习:优化登录界面,当点击登录按钮后,在该按钮对应的槽函数中,判断账户和密码框内的数据是否为admin和123456,如果账户密码匹配成功,则提示登录成功并关闭登录界面,如果账户和密码匹配失败,则提示登录失败,并将密码框中的内容清空。

    当点击取消按钮后,则关闭整个登录界面

    要求:对登录按钮使用QT5版本的连接,对取消按钮使用qt4版本的连接

    widget.cpp

    1. #include "widget.h"
    2. Widget::Widget(QWidget *parent)
    3. : QWidget(parent)
    4. {
    5. //设置页面
    6. this -> resize(540,410);
    7. this ->setFixedSize(540,410);
    8. this -> setWindowTitle("weifeng client");
    9. //this -> setStyleSheet("background-color:pink;");
    10. this -> setWindowIcon(QIcon(":/picture/ME.png"));
    11. //界面图
    12. lab1 = new QLabel(this);
    13. lab1 -> resize(540,150);
    14. lab1 -> setPixmap(QPixmap(":/picture/starcat.png"));
    15. lab1 -> setScaledContents(true);
    16. lab1->setStyleSheet("border-radius: 10px;");
    17. lab = new QLabel(this);
    18. lab -> resize(540,(410-150));
    19. lab -> move(0,lab1 -> height());
    20. lab -> setPixmap(QPixmap(":/picture/main-background.png"));
    21. lab -> setScaledContents(true);
    22. lab->setStyleSheet("border-radius: 10px;");
    23. effect = new QGraphicsOpacityEffect(); // 注意这里只影响 'lab'
    24. effect->setOpacity(0.4);
    25. lab->setGraphicsEffect(effect);
    26. //设置登录按键
    27. btn1 = new QPushButton("登录",this);
    28. btn1 -> move(145,300);
    29. btn1 -> resize(100,50);
    30. btn1 -> setIcon(QIcon(":/picture/16.gif"));
    31. connect(btn1,&QPushButton::clicked,this,&Widget::my_slot);
    32. //设置取消按键
    33. btn2 = new QPushButton("取消",this);
    34. btn2 -> move(btn1 -> x()+150,btn1 -> y());
    35. btn2 -> resize(100,50);
    36. btn2 -> setIcon(QIcon(":/picture/15.gif"));
    37. // btn2 -> connect(btn2,&QPushButton::clicked,this,&Widget::my_slot);//关闭
    38. btn2 -> connect(btn2,SIGNAL(clicked()),this,SLOT(close()));
    39. //账号前图片
    40. lab2 = new QLabel(this);
    41. lab2 -> resize(50,50);
    42. lab2 -> move(145,175);
    43. lab2 -> setPixmap(QPixmap(":/picture/08.gif"));
    44. lab2 -> setScaledContents(true);
    45. //密码前图片
    46. lab3 = new QLabel(this);
    47. lab3 -> resize(lab2 -> size());
    48. lab3 -> move(lab2 -> x(),lab2 -> y()+50);
    49. lab3 -> setPixmap(QPixmap(":/picture/12.gif"));
    50. lab3 -> setScaledContents(true);
    51. //账号
    52. font.setBold(true); //设置加粗
    53. lab4 = new QLabel("账号",this);
    54. lab4->setFixedHeight(30);
    55. lab4->setFont(font);
    56. lab4 -> move(lab2 -> x()+55,lab2 -> y()+20);
    57. //密码
    58. lab5 = new QLabel("密码",this);
    59. lab5 -> setFixedHeight(30);
    60. lab5 -> setFont(font);
    61. lab5 -> move(lab3 -> x()+55,lab3 -> y()+20);
    62. //账号栏
    63. edit1 = new QLineEdit(this);
    64. edit1 -> resize(140,lab4 -> height());
    65. edit1->setFixedHeight(30);
    66. edit1 -> move(lab4 -> x()+50,lab4 -> y());
    67. edit1 -> setPlaceholderText("QQ/手机/邮箱");
    68. //密码栏
    69. edit2 = new QLineEdit(this);
    70. edit2 -> resize(140,lab5 -> height());
    71. edit2->setFixedHeight(30);
    72. edit2 -> move(lab5 -> x()+50,lab5 -> y());
    73. edit2 -> setEchoMode(QLineEdit::Password);
    74. edit2 -> setPlaceholderText("密码");
    75. speecher = new QTextToSpeech(this);
    76. }
    77. void Widget::my_slot(){
    78. QString username = edit1 ->text();
    79. QString password = edit2 ->text();
    80. if(username == "admin"){
    81. if(password == "123456"){
    82. speecher -> say("登录成功");
    83. close();
    84. return;
    85. }
    86. }
    87. speecher -> say("登录失败");
    88. edit2->clear();
    89. }
    90. /*
    91. * 版本qt5
    92. void Widget::my_slot(){
    93. close();
    94. }
    95. */
    96. Widget::~Widget()
    97. {
    98. }

    main

    1. #include "widget.h"
    2. #include
    3. int main(int argc, char *argv[])
    4. {
    5. QApplication a(argc, argv);
    6. Widget w;
    7. w.show();
    8. return a.exec();
    9. }

    widget.h

    1. #ifndef WIDGET_H
    2. #define WIDGET_H
    3. #include
    4. #include
    5. #include
    6. #include
    7. #include
    8. #include
    9. #include
    10. #include
    11. #include
    12. #include
    13. #include
    14. #include
    15. class Widget : public QWidget
    16. {
    17. Q_OBJECT
    18. public:
    19. Widget(QWidget *parent = nullptr);
    20. ~Widget();
    21. signals:
    22. void my_signal();
    23. public slots:
    24. void my_slot();
    25. private:
    26. QLabel *lab1;
    27. QLabel *lab;
    28. QGraphicsOpacityEffect* effect;
    29. QPushButton *btn1;
    30. QPushButton *btn2;
    31. QLabel *lab2;
    32. QLabel *lab3;
    33. QFont font;
    34. QLabel *lab4;
    35. QLabel *lab5;
    36. QLineEdit *edit1;
    37. QLineEdit *edit2;
    38. QTextToSpeech *speecher;
    39. };
    40. #endif // WIDGET_H

     2.5信号函数与槽函数的总结

    一个信号函数发射出,多个相连接的槽函数都可执行

    一个槽函数也可以同时响应多个与他连接的信号,只要一个信号被发射,该槽函数就会被执行

    一个信号函数可以连接到另一个信号函数,一个被发射后一个也会被发射

    信号与槽函数参数表为了传参有以下准则

    1. 1、信号函数和槽函数进行链接时,一般要求信号函数和槽函数的参数保持一致
    2. connect(信号发送者, SIGNAL(signalFun()),信号接收者, SLOT(slotFun())); //Ok
    3. connect(信号发送者, SIGNAL(signalFun(int)),信号接收者, SLOT(slotFun(int))); //Ok
    4. connect(信号发送者, SIGNAL(signalFun(int, char)),信号接收者, SLOT(slotFun(int, char))); //Ok
    5. connect(信号发送者, SIGNAL(signalFun(char, int)),信号接收者, SLOT(slotFun(int, char))); //False
    6. connect(信号发送者, SIGNAL(signalFun(int)),信号接收者, SLOT(slotFun(char))); //False
    7. 2、当信号函数的参数大于槽函数的参数时
    8. connect(信号发送者, SIGNAL(signalFun(int, char)),信号接收者, SLOT(slotFun())); //Ok
    9. connect(信号发送者, SIGNAL(signalFun(int, char)),信号接收者, SLOT(slotFun(int))); //Ok
    10. connect(信号发送者, SIGNAL(signalFun(int, char)),信号接收者, SLOT(slotFun(char))); //False
    11. 3、当信号函数的参数小于槽函数的参数时
    12. connect(信号发送者, SIGNAL(signalFun(int)),信号接收者, SLOT(slotFun(int, char))); //False
    13. connect(信号发送者, SIGNAL(signalFun(int)),信号接收者, SLOT(slotFun(int, char=0))); //Ok

    1.多态,虚函数,纯虚函数

    多态:允许对象以多种方式存在,而多态分为静态和动态,

    静态多态就是函数重载/运算符重载和模板,是编译时多态,通过相同的函数名,不同的参数列表实现重载,模板就是提前假定一个类型进行,通过需要的类型传递后达成。

    动态多态是运行时多态,主要是通过虚函数实现函数重写,父类的指针或者引用,指向或初始化子类的对象,调用子类对父类重写的函数,进而展开子类的功能。

    虚函数:在动态多态中使用到,在函数前加上virtual关键字,父类中该函数是虚函数的话,允许继承的子类同名同类型函数对父类虚函数进行函数重写

    纯虚函数:当父类中虚函数被子类用来重写,且没有定义的意义,这个时候一般把父类的虚函数设置成纯虚函数,当子类对父类的虚函数重写时,且抽象类中无纯虚函数,即实例化成功,否则也是抽象类。

    2.将“引用”作为函数参数有哪些特点

    普通函数参数分为值传递和地址传递,值传递的参数值出了函数作用域后,空间收回无法影响实参值,地址传递是将地址传到函数中,能影响实参,但是需要额外申请指针大小的空间,所以在c++中引入的引用参数,由于引用与被引用的参数占同一片地址,所有既可以不另外申请空间,又能影响到原来的值,这样效率更高。当不想修改值时也可使用常引用。

    3.结构体和联合体有什么区别

    联合体中变量占据空间各不相同,但是联合体中共同占用一块空间

    结构体中每个成员也有独立的值,而联合体中修改一个成员的值也会修改到其他成员

    结构体计算大小时满足字节对齐原则,而联合体中不是,主要看最大元素大小

  • 相关阅读:
    Delphi中资源文件使用详解
    9HTML
    Express--获取URL中携带的查询参数、获取URL中的动态参数、获取URL中的动态参数
    一文读懂Java中的String类之助力Java进阶之路
    算法12.从暴力递归到动态规划5
    MQTT协议是什么?快速了解MQTT协议在物联网中的应用
    独立站投放谷歌广告是应该找代理商
    servlet 教程 1:环境搭建和新建 servlet 项目
    2021年数维杯数学建模C题运动会优化比赛模式探索求解全过程文档及程序
    【Redis】链表和字典
  • 原文地址:https://blog.csdn.net/weixin_69028524/article/details/132609360