Posted on 

Qt乱谈

一些我学到的我用到的且跟C++有区别的地方

先说Qt,一个完全面向对象的C++图形用户界面应用程序框架

试图驯化Qt简单地开发个小游戏,程序到今天算是收尾了🧐

1、QDubug

一个调试输出功能的库

1
2
3
#include <QDebug> --声明头文件
//输出的一种最常用格式
qDebug()<<"score:"<<score;

2、 对象树

  • QObject是以对象树的形式组织起来的
    • 当我们创建一个QObject对象时,可以设置这个对象的父对象parent,这个被创建的对象会自动添加到其父对象的children()列表里(注意此父对象非继承意义上的父类
  • 当父对象析构的时候,其children()列表中的所有对象也会被析构
  • QWidget是能够在屏幕上显示的一切组件的父类
  • 局部对象的析构顺序按照其创建顺序的相反过程

3、信号与槽

1
2
connect(sender, signal, receiver, slot)
connect(信号发送者, 发送的具体信号, 信号接受者, 信号的处理(槽函数))

优点:松散耦合,信号发送端和接收端本身无关联,通过connect连接耦合。

  • 信号和槽函数返回值是 void
  • 信号只需要声明,不需要实现,槽函数既要声明也需要实现
  • 断开信号 disconnect()

3.1、自定义信号和槽

  • 自定义信号:emit发送信号—— emit 对象指针->信号()

  • 信号槽要求信号和槽的参数一致,所谓一致,是参数类型一致。

  • 重载冲突:连接带参数的 信号与槽

    • 需要利用函数指针 -> 明确指向的函数地址
1
2
3
4
void(类1:: *函数指针1)(所带参数类型) = &类1::信号1;
void(类2:: *函数指针2)(所带参数类型) = &类2::信号2;
connect(sender, signal, receiver, slot);
调用自定义信号函数Func();
1
2
3
4
5
6
7
8
9
10
// 无参信号和槽连接
void(Teacher:: *teacherSignal)(QString) = &Teacher::signal1;
void(Student:: *studentSlot)(QString) = &Student::slot1;
connect(ls,teacherSignal,xs,studentSlot);
Func();
// 按钮控制信号和槽
QPushButton * btn = new QPushButton("下课",this)
connect(btn,&QPushButton::clicked,this,&Widge::Func)
// 信号连接信号
connect(btn,&QPushButtomn,ls,teacherSignal)

3.2、lambda表达式

用于定义和创建匿名的函数对象

1
2
[函数对象参数](操作符重载函数参数)mutable->返回值{函数体}
// 其中 mutable 看需求是否添加
  • 函数对象参数

    [] 标识一个lambda的开始,不能省略
    [] 没有使用任何函数对象参数
    [=] 可使用lambda所在范围内所有可见的局部变量,值传递
    [&] 可使用lambda所在范围内所有可见的局部变量,引用传递
    [this] 函数体内可使用lambda所在类中的成员变量
    [a] a按值传递,默认函数是const
    [&a] a按引用传递

4、定时器

  • 利用事件

    1
    2
    3
    4
    5
    6
    7
    8
    9
    void timerEvent(QTimeEvent * ev);
    //启动定时器
    startTimer(1000) // 参数1 间隔 单位毫秒
    // 多个定时器
    id1 = startTimer(1000)
    if(ev->timerId()==id1){ // 判断唯一标示
    static int num = 1;
    ui->label->setText(QString::number(num++));
    }
  • 利用定时器类 QTimer

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    // 创建定时器对象
    QTimer * timer(){
    // 启动定时器
    timer->start(1000);
    // 停止定时器
    // timer->stop();
    // 发送timeout信号监听,lambda匿名函数实现
    connect(timer, QTimer::timeout, [=](){
    static int num = 1;
    ui->label->setText(QString(num++));
    })
    }

5、QPainter 绘图事件

1
2
3
4
5
6
7
8
// 声明绘图事件
void paintEvent(QPainEvent *);
// 实例化画家对象 this指的绘图设备
QPainter painter(this);
// 画图片
painter.drawPixmap(int x,int y,int w,int h,const QPixmap &pm);
painter.drawPixmap(QRect(int x,int y,int w,int h),const QPixmap &pm);
// 如果要手动调用绘图事件,可用update()

6、QVector 容器(动态数组)

1
vector<数据类型*> 容器名
1
2
vector<类1 *> vector1;  // 装类1的容器vector1
vector<类1 *>::iterator it; // 名为it的迭代器,可遍历和操作容器
  • 遍历和操作容器
1
2
3
4
for(it=vector1.begin();it!=vector1.end();){
if((*it)->done()){
it=vector1.erase(it);
}

erase():从容器中删除指定位置的元素,并返回指向被删除元素之后位置的迭代器

7、QSound 音乐音效

1
2
3
4
5
// 在导入QSound时,需要先在 .pro工程文件中加入
QT += multimedia
//
#include<QSound>

1
QSound::play(音乐);

数据类型转换

  • QString -> char *

    1
    2
    // 先转成 QByteArray [.toUtf8()] 再转成 char * [ .data()]
    qDebug() << str1.toUtf8().data();
  • 子类—>父类

    1
    2
    3
    // 强制类型转换符static_cast
    // 例如父类QEvent * e, 子类QMouseEvent * ev
    QMouseEvent * ev = static_cast<QMouseEvent *>(e);

一些报错

0x01 No rule to make target ‘……’, needed by ‘……’. Stop.

这个报错可能是 .pro 文件里面有重复的头文件,删除掉重修构建就好了

0x02 The inferior stopped because it received a signal from the operating system.

这个报错通常是由于访问无效的内存地址引起的,会使得程序异常结束,后来回去看代码找到这个我释放了空间但是又试图访问的地方改掉就好了



Copyright © 2022 - 2023 BlindArbiter

Powered by Hexo | Theme - Stellar