0926-27,元对象模型,信号和槽函数,connect函数,事件处理的详细过程,widgets模块

news2024/9/30 3:13:57

0926

QMetaProperty   //创建一个支持元对象系统的类

myclass.h
#ifndef MYCLASS_H
#define MYCLASS_H

#include <QObject>

class myclass : public QObject
{
    Q_OBJECT
    //定义了名字位health的动态属性,对应的底层是m_health
    Q_PROPERTY(int health MEMBER m_health)
    Q_PROPERTY(int mana MEMBER m_mana)
public:
    explicit myclass(QObject *parent = nullptr);

//signals:
private:
    int m_health;
    int m_mana;

};
//继承QObject,QObject必须是第一个基类
//类的私有域添加Q_OBJECT宏
//类的定义不能放在main.cpp文件(不支持MOC
//头文件保护

#endif // MYCLASS_H
myclass.cpp
#include "myclass.h"

myclass::myclass(QObject *parent) : QObject(parent),m_health(100),m_mana(100)
{

}
main.cc
#include "mainwindow.h"
#include "myclass.h"

#include <QApplication>
#include <QMetaObject>
#include <QMetaProperty>
#include <QDebug>


void loss(QObject*monster,const char* property){
    const QMetaObject* meta=monster->metaObject();
    //Q_OBJECT宏引入的,返回指向该对象的元对象的指针
    qDebug()<<"property count= "<<meta->propertyCount();
    for(int i=0;i<meta->propertyCount();++i){
        //遍历所有的动态属性
        QMetaProperty metaProperty=meta->property(i);
        qDebug()<<metaProperty.name();
    }

    //根据属性的名字找到下标
    int index=meta->indexOfProperty(property);
    QMetaProperty metaProperty=meta->property(index);
    int current=metaProperty.read(monster).toInt();
    qDebug()<<property<<"   "<<current;
    ++current;
    metaProperty.write(monster,current);
}

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    myclass monster;
    loss(&monster,"health");
    loss(&monster,"mana");
    return a.exec();
}

signal_slot   //创建自定义的信号和槽函数,携带参数,多次connect,去重连接

a.h
#ifndef A_H
#define A_H

#include <QObject>

class A : public QObject
{
    Q_OBJECT
public:
    explicit A(QObject *parent = nullptr);

signals:
    void a_signal0();
    void a_signal1(int x);
    void a_signal1();

//如何设计一个自定义信号
    //元对象系统  访问权限修饰符signals  返回值void的成员函数,只声明不定义
};



class B : public QObject
{
    Q_OBJECT
public:
    explicit B(QObject *parent = nullptr);

public slots:
    void b_slot0();
    void b_slot1(int x);
    void b_slot1();
//如果设计一个自定义的槽函数
    //元对象系统 访问权限修饰符public/privated/protected slots
    //参数和返回值和信号匹配的成员函数  写定义

};

#endif // A_H
a.cpp
#include "a.h"
#include <QDebug>
#include <QtWidgets/QtWidgets>

A::A(QObject *parent) : QObject(parent)
{

}

B::B(QObject *parent) : QObject(parent)
{

}



void B::b_slot0(){
    qDebug()<<"b_solt 0000";
    //Sleep(3000);
    qDebug()<<"b_solt 0000";
}
void B::b_slot1(int x){
    qDebug()<<"b+slot 1111__"<<x;
}

void B::b_slot1(){
    qDebug()<<"b+slot 1111";
}
main.cpp
#include "mainwindow.h"
#include "a.h"

#include <QApplication>
#include <QDebug>

int main(int argc, char *argv[])
{
    QApplication app(argc, argv);

    A a;
    B b;

    //SIGNAL SLOT   运行时错误
//    QObject::connect(&a,SIGNAL(a_signal0()),
//                     &b,SLOT(b_slot0()));
    //指向成员函数的指针   编译时错误
//    QObject::connect(&a,&A::a_signal0,&b,&B::b_slot0);
//    qDebug()<<"before emit";
//    emit a.a_signal0();
//    emit a.a_signal0();
//    qDebug()<<"after emit";

//    QObject::connect(&a,SIGNAL(a_signal1(int)),
//                     &b,SLOT(b_slot1(int)));
//    emit a.a_signal1(12241);
//信号的参数可以多,不可以少,报错时机有差别

//    QObject::connect(&a,QOverload<int>::of(&A::a_signal1),
//                     &b,QOverload<int>::of(&B::b_slot1));
//    emit a.a_signal1(5345);

//    QObject::connect(&a,QOverload<>::of(&A::a_signal1),
//                     &b,QOverload<>::of(&B::b_slot1));
//    emit a.a_signal1();



//    //1 signal  connect  2 slot  发送一次信号依次调用
//    QObject::connect(&a,QOverload<>::of(&A::a_signal0),
//                      &b,QOverload<>::of(&B::b_slot0));
//    QObject::connect(&a,QOverload<>::of(&A::a_signal0),
//                      &b,QOverload<>::of(&B::b_slot1));
//    emit a.a_signal0();



//    //相同的connect两次  --->  solt执行两次
//    QObject::connect(&a,QOverload<>::of(&A::a_signal0),
//                      &b,QOverload<>::of(&B::b_slot0));
//    QObject::connect(&a,QOverload<>::of(&A::a_signal0),
//                      &b,QOverload<>::of(&B::b_slot0));
//    emit a.a_signal0();




    //connect多次  --->  加上状态 不会重复发送
    QObject::connect(&a,&A::a_signal0,
                      &b,&B::b_slot0,
                     Qt::ConnectionType(Qt::AutoConnection|Qt::UniqueConnection));
    QObject::connect(&a,&A::a_signal0,
                      &b,QOverload<>::of(&B::b_slot1),
                     Qt::ConnectionType(Qt::AutoConnection|Qt::UniqueConnection));
    QObject::connect(&a,&A::a_signal0,
                      &b,QOverload<>::of(&B::b_slot1),
                     Qt::ConnectionType(Qt::AutoConnection|Qt::UniqueConnection));
    QObject::connect(&a,&A::a_signal0,
                      &b,QOverload<>::of(&B::b_slot1),
                     Qt::ConnectionType(Qt::AutoConnection|Qt::UniqueConnection));
    emit a.a_signal0();



    return app.exec();
}

signal_slot _complex    //槽函数执行过程中发射信号

a.h
#ifndef A_H
#define A_H

#include <QObject>
#include <QDebug>

class A : public QObject
{
    Q_OBJECT
public:
    explicit A(QObject *parent = nullptr);

signals:
    void a_signal();
};


class B : public QObject
{
    Q_OBJECT
public:
    explicit B(QObject *parent = nullptr);
signals:
    void b_signal();
public slots:
    void b_slot(){
        qDebug()<<"b_slot";
        emit b_signal();
    }
};


class C : public QObject
{
    Q_OBJECT
public:
    explicit C(QObject *parent = nullptr);

public slots:
    void c_slot(){
        qDebug()<<"c_slot";
    }

};




#endif // A_H
mian.cpp
#include "mainwindow.h"
#include "a.h"
#include <QApplication>

int main(int argc, char *argv[])
{
    QApplication app(argc, argv);

    A a;
    B b;
    C c;

    //槽函数可以发射信号
//    QObject::connect(&a,&A::a_signal,&b,&B::b_slot);
//    QObject::connect(&b,&B::b_signal,&c,&C::c_slot);
//    emit a.a_signal();


    //信号可以当槽函数使用
//    QObject::connect(&a,&A::a_signal,&b,&B::b_signal);
//    QObject::connect(&b,&B::b_signal,&c,&C::c_slot);
//    emit a.a_signal();

    //栈溢出
//    QObject::connect(&a,&A::a_signal,&b,&B::b_slot);
//    QObject::connect(&b,&B::b_signal,&a,&A::a_signal);
//    emit a.a_signal();

    QObject::connect(&a,&A::a_signal,[](){
       qDebug()<<"hello world!";
    });
    emit a.a_signal();


    return app.exec();
}

pingpong    //自己给自己发消息

a.h

#ifndef A_H
#define A_H

#include <QObject>
#include <QDebug>


class A : public QObject
{
    Q_OBJECT
public:
    explicit A(QObject *parent = nullptr);

signals:
    void a_signal();
private slots:
    void a_slot(){
        qDebug() << "a_slot";
        emit a_signal();
    }
};

#endif // A_H

a.cpp

#include "a.h"

A::A(QObject *parent) : QObject(parent)
{
    QObject::connect(this,&A::a_signal,this,&A::a_slot);
}

sender()   //在槽函数中,返回发出该信号的信号的指针(pushbutton)

mainwindow.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>

QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
QT_END_NAMESPACE

class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    MainWindow(QWidget *parent = nullptr);
    ~MainWindow();
private slots:
    void do_mmslot();
private:
    Ui::MainWindow *ui;
};
#endif // MAINWINDOW_H
mainwindow.cpp
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QDebug>

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
{
    ui->setupUi(this);

    QObject::connect(ui->b1,&QPushButton::clicked,this,&MainWindow::do_mmslot);
    QObject::connect(ui->b2,&QPushButton::clicked,this,&MainWindow::do_mmslot);
    QObject::connect(ui->b3,&QPushButton::clicked,this,&MainWindow::do_mmslot);
}

void MainWindow::do_mmslot(){
    qDebug()<<"hello";
    qDebug()<<sender();
    QPushButton *b=qobject_cast<QPushButton*>(sender());
    b->setText("hell");
}

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

0927   

tree   //创建树结构

my_widgets.h    //过滤事件,毁灭吧世界,老师的也没有跑过滤掉
#ifndef CC_H
#define CC_H

#include <QWidget>
#include <QDebug>
#include <QEvent>
#include <QMouseEvent>

class CC : public QWidget
{
    Q_OBJECT
public:
     explicit CC(QWidget *parent = nullptr);

//    bool event(QEvent *ev) override {
//        qDebug() << "MyWidget event()" << ev->type();
//        if (ev->type() == QEvent::MouseButtonPress) {
//            return true; // 完全过滤掉 MouseButtonPress 事件
//        }
//        return QWidget::event(ev); // 处理其他事件
//    }

//    void mousePressEvent(QMouseEvent *ev) override {
        qDebug() << "PPP  MyWidget event handler()" << ev->pos();
//        qDebug() << "aaaaaaaaaaaaaaaaaaaa" << ev->pos();
        QWidget::mousePressEvent(ev); // 可选,根据需要决定是否调用
//    }

//    void mouseReleaseEvent(QMouseEvent *ev) override {
//        qDebug() << "RRRR   MyWidget event handler()" << ev->pos();
//        QWidget::mouseReleaseEvent(ev); // 正确调用 mouseReleaseEvent
//    }

    bool event(QEvent *ev) override {
            qDebug() << "MyWidget event()" << ev->type();
            if(ev->type() == QEvent::MouseButtonPress){
                return false;
            }
            //在子类的虚函数中调用父类的虚函数
            return QWidget::event(ev);
        }

        void mousePressEvent(QMouseEvent *ev) override{
            qDebug() << "MyWidget event handler()" << ev->pos();
            QWidget::mousePressEvent(ev);
        }
        void mouseReleaseEvent(QMouseEvent *ev) override{
            qDebug() << "MyWidget event handler()" << ev->pos();
            QWidget::mousePressEvent(ev);
        }


signals:

};

#endif // CC_H
main.cpp
#include "mainwindow.h"
#include "cc.h"

#include <QApplication>
#include <QEvent>

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
//    MainWindow w;
    CC c;
    c.show();
//    w.show();
    return a.exec();
}

0926作业

01 实现一个井字棋 点击空白按钮可以显示'X'或者'O'       //坏了,一次回退了两个,先这样吧

mainwindow.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>
#include <QList>
#include <QStack>
#include <QPushButton>

QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
QT_END_NAMESPACE

class MainWindow : public QMainWindow
{
    Q_OBJECT

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


private slots:

    void do_play();
    void on_bt_clear_clicked();
    void on_bt_undo_clicked();

private:
    Ui::MainWindow *ui;
    QList<QPushButton *> btlist; //按钮deque
    QStack<int> opstack;  //操作栈,回退
    QString currUser;//当前玩家/o/x
};
#endif // MAINWINDOW_H
mainwindow.cpp
#include "mainwindow.h"
#include "ui_mainwindow.h"

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
{
    ui->setupUi(this);

    //QList<QPushButton *> btlist; //按钮deque
    btlist<<ui->bt1<<ui->bt2<<ui->bt3<<ui->bt4<<ui->bt5
            <<ui->bt6<<ui->bt7<<ui->bt8<<ui->bt9;
//    QStack<int> opstack;  //操作栈,回退
    //QString currUser="X";//当前玩家/o/x

     //发出信号的对象  信号  接收方  槽函数
    for(int i=0;i<btlist.size();++i){
        QMainWindow::connect(btlist[i],&QPushButton::clicked,this,&MainWindow::do_play);
    }
    QMainWindow::connect(ui->bt_undo,&QPushButton::clicked,this,&MainWindow::on_bt_undo_clicked);
    QMainWindow::connect(ui->bt_clear,&QPushButton::clicked,this,&MainWindow::on_bt_clear_clicked);

}

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

void MainWindow::do_play(){
    //获取按钮

    //检查按钮内容是否为空,不为空,返回不执行下面的操作
    QPushButton *nowbt=qobject_cast<QPushButton*>(sender());
    if(!nowbt->text().isEmpty()){
        return;
    }

     nowbt->setText(currUser);
    int nownum=btlist.indexOf(nowbt);
    currUser = (currUser == "O") ? "X" : "O";

    opstack.push(nownum);//stack.push 压栈
}

void MainWindow::on_bt_undo_clicked(){
    if(opstack.isEmpty()){return;}
    QPushButton *bfbt=btlist[opstack.pop()];
    bfbt->setText("");
    currUser = (currUser == "O") ? "X" : "O";
}

void MainWindow::on_bt_clear_clicked()
{

    opstack.clear();
    for(int i=0;i<btlist.size();++i){
        btlist[i]->setText("");
    }
}

02 根据如下ui绘制一个计算器,先不实现计算的功能,只实现显示表达式和编辑表达式的功能

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>
#include <QPushButton>

QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
QT_END_NAMESPACE

class MainWindow : public QMainWindow
{
    Q_OBJECT

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

private slots:



    //检查最后一个字符
     bool _check_last_isnumber();
     void _check_and_clear();

    void do_pushButton_number();



    void do_pushButton_symbol();

    void on_pushButton_c_clicked();//清空
    void on_pushButton_del_clicked();//回退

    void on_pushButton_deng_clicked();//等号




private:
    Ui::MainWindow *ui;
    QString _current_text;
    bool _is_expression_valid;//是否有表达式


};
#endif // MAINWINDOW_H
#include "mainwindow.h"
#include "ui_mainwindow.h"


MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
{
    ui->setupUi(this);

    QString _current_text="hello";
    ui->label->setText(_current_text);
    bool _is_expression_valid=false;

    QObject::connect(ui->pushButton_0,&QPushButton::clicked,
                     this,&MainWindow::do_pushButton_number);
    QObject::connect(ui->pushButton_1,&QPushButton::clicked,
                     this,&MainWindow::do_pushButton_number);
    QObject::connect(ui->pushButton_2,&QPushButton::clicked,
                     this,&MainWindow::do_pushButton_number);
    QObject::connect(ui->pushButton_3,&QPushButton::clicked,
                     this,&MainWindow::do_pushButton_number);
    QObject::connect(ui->pushButton_4,&QPushButton::clicked,
                     this,&MainWindow::do_pushButton_number);
    QObject::connect(ui->pushButton_5,&QPushButton::clicked,
                     this,&MainWindow::do_pushButton_number);
    QObject::connect(ui->pushButton_6,&QPushButton::clicked,
                     this,&MainWindow::do_pushButton_number);
    QObject::connect(ui->pushButton_7,&QPushButton::clicked,
                     this,&MainWindow::do_pushButton_number);
    QObject::connect(ui->pushButton_8,&QPushButton::clicked,
                     this,&MainWindow::do_pushButton_number);
    QObject::connect(ui->pushButton_9,&QPushButton::clicked,
                     this,&MainWindow::do_pushButton_number);


    QObject::connect(ui->pushButton_jia,&QPushButton::clicked,
                     this,&MainWindow::do_pushButton_symbol);
    QObject::connect(ui->pushButton_jian,&QPushButton::clicked,
                     this,&MainWindow::do_pushButton_symbol);
    QObject::connect(ui->pushButton_chu,&QPushButton::clicked,
                     this,&MainWindow::do_pushButton_symbol);
    QObject::connect(ui->pushButton_cheng,&QPushButton::clicked,
                     this,&MainWindow::do_pushButton_symbol);
    QObject::connect(ui->pushButton_dian,&QPushButton::clicked,
                      this,&MainWindow::do_pushButton_symbol);
    QObject::connect(ui->pushButton_010,&QPushButton::clicked,
                      this,&MainWindow::do_pushButton_symbol);


}

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

//最后一位数字
bool MainWindow::_check_last_isnumber(){
    if(!_current_text.isEmpty()&&_current_text[_current_text.length()-1].isDigit()){
        return true;
    }
    return false;
}

//是否第一次输入
void MainWindow::_check_and_clear(){
    if(!_is_expression_valid){
        _current_text.clear(); // 清空当前表达式
        _is_expression_valid = true;  // 将有效标志设置为true
    }
}


void MainWindow::do_pushButton_number()
{
   _check_and_clear();
   QPushButton *currbt=qobject_cast<QPushButton*>(sender());
   _current_text.append(currbt->text());
   ui->label->setText(_current_text);
}

void MainWindow::do_pushButton_symbol(){
    _check_and_clear();
    QPushButton *currbt=qobject_cast<QPushButton*>(sender());
    if(_check_last_isnumber()){
        _current_text.append(currbt->text());
        ui->label->setText(_current_text);
    }else{
        ui->label->setText(_current_text);
    }

}


//c  清空
void MainWindow::on_pushButton_c_clicked()
{
    _current_text.clear();
    ui->label->setText("hello");
    _is_expression_valid=false;
}


void MainWindow::on_pushButton_del_clicked()
{
    _check_and_clear();
    _current_text.chop(1);
    ui->label->setText(_current_text);
}



//等于  清空  输出  设置表达式
void MainWindow::on_pushButton_deng_clicked()
{
    _current_text.clear();
    ui->label->setText("result is ...");
    _is_expression_valid=false;
}

03 简述信号和槽机制的优势和劣势

优势,在频繁进行对象间通信的情况下,信号槽机制使得代码变得优雅,可扩展性好

优势:1,松耦合,2,类型安全3,关联自由 4,生态(QT有很多自带的信号和槽

劣势,牺牲了一部分的性能开销

优势

解耦:信号和槽允许对象间的松耦合。发送信号的对象不需要知道接收信号的对象的具体类型或实现,从而提高了代码的灵活性和可重用性。
易于维护:由于对象之间的耦合度低,修改一个类的实现不会影响到其他类,只要信号和槽的接口保持不变。
多对多连接:一个信号可以连接多个槽,反之亦然。这使得同一个事件可以被多个处理程序响应,增强了系统的扩展性。
线程安全:在 Qt 中,信号和槽机制支持跨线程通信,能够自动处理线程间的调用,使得多线程编程更加简单和安全。
简洁的语法:Qt 提供了方便的宏和模板,使得连接信号和槽的代码简单易读,减少了样板代码的数量。

劣势

调试困难:当信号和槽链复杂时,调试可能变得困难。找到信号的源头和对应的槽可能需要更多的时间和精力。
性能开销:信号和槽的机制引入了一定的性能开销,尤其是在连接大量信号和槽时,可能会影响系统的性能。
隐式行为:信号的发射和槽的调用是隐式的,可能导致程序的执行流不够清晰,特别是对于大型项目,容易让开发者感到混乱。
编译依赖:使用信号和槽需要使用 Qt 的元对象系统,这意味着在编译时需要依赖 moc(元对象编译器),增加了构建过程的复杂性。
类型安全:虽然 Qt 提供类型安全的连接,但如果不小心使用错误的参数类型,可能会导致运行时错误,而不是编译时错误。

04 信号和槽机制的目的是什么?书写代码实现一个自定义信号和自定义槽函数

目的是为了——松耦合,实现对象之间的通信但是不需要创建接收方的对象,提高代码的灵活性和可扩展性

05 connect函数有几种重载形式?哪一种更好为什么?

三种,

1,SIGNAL,SLOT,函数以字符串的形式传入,不推荐,会在运行时报错

2,使用成员函数的指针形式(会有函数重载的问题,通过QOverload携带参数信息解决

3,槽函数是一个函数对象,适用于不想使用继承的


QMetaObject::Connection 
connect(const QObject *sender, const char *signal, const QObject *receiver,
 const char *method, Qt::ConnectionType type = Qt::AutoConnection)
    使用字符串形式的信号和槽/*
sender: 发出信号的对象。
signal: 信号的名称,以字符串形式表示(例如,"clicked()")。
receiver: 响应信号的对象。
method: 槽的名称,以字符串形式表示(例如,"onButtonClicked()")。
type: 连接类型,可以是 Qt::AutoConnection、Qt::DirectConnection 或 Qt::QueuedConnection。
用法:适用于简单的信号槽连接,通常使用字符串来表示信号和槽的名称。这种方式会在运行时进行解析,可能会影响性能,但使用方便,特别是在动态创建对象时。*/
    
    
QMetaObject::Connection 
connect(const QObject *sender, const QMetaMethod &signal, const QObject *receiver, 
const QMetaMethod &method, Qt::ConnectionType type = Qt::AutoConnection)
    使用QMetaMethod/*
sender: 发出信号的对象。
signal: 信号的 QMetaMethod 对象,提供了更强的类型安全性。
receiver: 响应信号的对象。
method: 槽的 QMetaMethod 对象。
type: 连接类型。
用法:使用 QMetaMethod 可以避免字符串解析带来的性能损失,同时提供编译时检查,提高代码的安全性和可维护性。*/
    
    
QMetaObject::Connection 
connect(const QObject *sender, PointerToMemberFunction signal, const QObject *receiver, 
PointerToMemberFunction method, Qt::ConnectionType type = Qt::AutoConnection)
    使用指向成员函数的指针/*
sender: 发出信号的对象。
signal: 指向成员函数的指针,表示信号。
receiver: 响应信号的对象。
method: 指向成员函数的指针,表示槽。
type: 连接类型。
用法:这种方式提供了更强的类型安全性,因为成员函数指针在编译时就会被检查。适用于静态分析和代码优化*/
    
    
QMetaObject::Connection 
connect(const QObject *sender, PointerToMemberFunction signal, Functor functor)
    使用自定义可调用对象/*
sender: 发出信号的对象。
signal: 指向成员函数的指针,表示信号。
functor: 自定义可调用对象(如 Lambda 表达式或函数对象)。
用法:适用于将信号连接到不属于 QObject 派生类的函数或对象,非常灵活,可以使用任何符合函数签名的可调用对象。*/
    
    
    
QMetaObject::Connection 
connect(const QObject *sender, PointerToMemberFunction signal, const QObject *context, 
Functor functor, Qt::ConnectionType type = Qt::AutoConnection)
    带上下文的自定义可调用对象/*
sender: 发出信号的对象。
signal: 指向成员函数的指针,表示信号。
context: 上下文对象,通常用于确定信号的作用域。
functor: 自定义可调用对象。
type: 连接类型。
用法:类似于第 4 种,但可以指定上下文,确保在特定对象的上下文中处理信号,适合需要特定上下文的情况*/

06 在有三个对象A,B,C需要实现下面效果:

A发射信号会导致 B调用槽函数 C调用槽函数

B发射信号会导致 C调用槽函数

C发射信号会导致 A发射信号

a.h

#ifndef A_H
#define A_H

#include <QObject>
#include <QDebug>

class A : public QObject
{
    Q_OBJECT
public:
    explicit A(QObject *parent = nullptr);

signals:
    void a_signal();
};


class B : public QObject
{
    Q_OBJECT
public:
    explicit B(QObject *parent = nullptr);
signals:
    void b_signal();
public slots:
    void b_slot(){
        qDebug()<<"b_slot";
        emit b_signal();
    }
};


class C : public QObject
{
    Q_OBJECT
public:
    explicit C(QObject *parent = nullptr);

signals:
    void c_signal();
public slots:
    void c_slot(){
        qDebug()<<"c_slot";
    }

};




#endif // A_H

main.cpp

#include "mainwindow.h"
#include "a.h"
#include <QApplication>

int main(int argc, char *argv[])
{
    QApplication app(argc, argv);

    A a;
    B b;
    C c;

    QObject::connect(&a,&A::a_signal,&b,&B::b_slot);
    QObject::connect(&b,&B::b_signal,&c,&C::c_slot);
    emit a.a_signal();

    emit b.b_signal();

    QObject::connect(&c,&C::c_signal,&a,&A::a_signal);
    emit c.c_signal();

    return app.exec();
}

927作业

01 简述事件的产生、分发和处理流程,中间会产生哪些类型的对象,调用了什么方法。

02 实现一个“打蚊子”游戏

在屏幕中央有一个600*400的QWidget,一个用来统计分数的QLabel

一开始会在QWidget内部随机位置生成一个蚊子,当鼠标点击到蚊子以后,旧蚊子消失然后在另一个位置生成新的蚊子,分数增加。

提示:这里需要继承QWidget类然后重写paintEvent,在paintEvent当中可以创建QPainter对象绘制各种图形和图片

03 现在有三个对象ABC,A的父亲是B,B的父亲是C

点击A的内部,要求执行:

A的event和event_handler

B的event

C的event和event_handler

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2178459.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

C++进阶知识2 多态

多态 1. 多态的概念2. 多态的定义及实现2.1 多态的构成条件2.1.2 虚函数2.1.3 虚函数的重写/覆盖2.1.5 虚函数重写的⼀些其他问题2.1.6 override和final关键字2.1.7 重载/重写/隐藏的对⽐ 3. 多态的原理3.2 多态的原理3.2.1 多态是如何实现的3.2.2 动态绑定与静态绑定3.2.3 虚函…

828华为云征文|部署在线文档应用程序 CodeX Docs

828华为云征文&#xff5c;部署在线文档应用程序 CodeX Docs 一、Flexus云服务器X实例介绍二、Flexus云服务器X实例配置2.1 重置密码2.2 服务器连接2.3 安全组配置2.4 Docker 环境搭建 三、Flexus云服务器X实例部署 CodeX Docs3.1 CodeX Docs 介绍3.2 CodeX Docs 部署3.3 CodeX…

SpringBoot整合JPA 基础使用

一、什么是JPA ‌‌1.JPA的定义和基本概念‌‌ ‌JPA&#xff08;Java Persistence API&#xff09;‌是Java中用于进行持久化操作的一种规范&#xff0c;它定义了一系列用于操作关系型数据库的API接口。通过这些接口&#xff0c;开发人员可以方便地进行数据库的增删改查等操…

ArcgisEngine开发中,Ifeatureclass.Addfield 报错0x80040655处理方法

1、ArcgisEngine开发中&#xff0c;Ifeatureclass.Addfield 报错0x80040655。如下图所示。 2、经分析&#xff0c;这是由于字段类型错误&#xff0c;经检查&#xff0c;是由于字段名为中文名&#xff0c;超出shp格式的最大字段长度量&#xff0c;看资料说是5个中文字符&#xf…

fastadmin 搜索提交重置按钮文本修改

默认 修改require-backend.min.js文件 效果 当然最好还是去需修改lang文件 效果 如果修改没生效记得清楚一下缓存&#xff0c;再刷新 完结 赠人玫瑰&#xff0c;手有余香&#xff01;如果文章内容对你有所帮助&#xff0c;请不要吝啬你的点赞评论和关注&#xff0c;你…

校园跑腿系统二手市场校园搭子校园社团活动系统2000的和4800的有什么区别

校园跑腿系统、二手市场、校园搭子、校园社团活动系统在不同价格档位&#xff08;如2000元和4800元&#xff09;之间可能存在多方面的区别&#xff0c;这些区别主要体现在功能丰富性、技术支持、用户体验、定制化程度以及后续服务等方面。然而&#xff0c;由于具体的价格差异和…

TDengine 流计算与窗口机制的深度解析:揭示计数窗口的关键作用

在 TDengine 3.2.3.0 版本中&#xff0c;我们针对流式计算新增了计数窗口&#xff0c;进一步优化了流式数据处理的能力。本文将为大家解读流式计算与几大窗口的关系&#xff0c;并针对新增的计数窗口进行详细的介绍&#xff0c;帮助大家进一步了解 TDengine 流式计算&#xff0…

趣味SQL | 从围棋收官到秦楚大战的数据库SQL实现(下)

目录 0 上集回顾 1 双先量化&#xff0c;得失权衡 2 各守城池&#xff0c;妥协攻守 3 SQL演算&#xff0c;三策评详 4 寸土必争&#xff0c;利益倍增 5 SQL再演&#xff0c;策略精进 6 棋道相通&#xff0c;治国有术 如果觉得本文对你有帮助&#xff0c;那么不妨也可…

这是我见过最强的AI大模型教程书籍!免费白嫖,可以上车!!

这是LLM入门级书籍&#xff0c;共145页&#xff0c;主要介绍了大型语言模型&#xff08;LLM&#xff09;的基本原理和底层技术。 阅读本书&#xff0c;您将能够掌握 LLM 的基本概念&#xff0c;了解自然语言处理&#xff08;NLP&#xff09;的发展历程&#xff0c;理解 Transf…

家中浮毛太多怎么办?希喂、米家、安德迈更推荐哪款?

在现代养宠家庭生活中&#xff0c;宠物空气净化器已经成为不可或缺的家电之一。 而在众多空气净化器类型中&#xff0c;宠物空气净化器以其独特的设计和卓越的净化效果&#xff0c;逐渐赢得了越来越多养宠家庭的青睐。 它不仅能有效地吸附空中飞舞的浮毛&#xff0c;还能高效…

召回10 Deep Retrieval召回

Deep Retrieval召回&#xff1a;给定用户特征采用beam search算法召回路径&#xff0c;根据路径召回物品&#xff0c;对物品排序&#xff0c;最终用分数高的物品作为召回结果。 双塔模型是将向量表征作为用户和物品之间的中介。 Deep Retrieval是将路径作为用户和物品之间的中介…

基于Java+VUE+echarts大数据智能道路交通信息统计分析管理系统的设计与实现

大数据智能交通管理系统是一种基于Web的系统架构&#xff0c;通过浏览器/服务器&#xff08;B/S&#xff09;模式实现对城市交通数据的高效管理和智能化处理。该系统旨在通过集成各类交通数据&#xff0c;包括但不限于车辆信息、行驶记录、违章情况等&#xff0c;来提升城市管理…

场地预约系统小程序的设计

管理员账户功能包括&#xff1a;系统首页&#xff0c;个人中心&#xff0c;用户管理&#xff0c;场地类型管理&#xff0c;场地信息管理&#xff0c;我的预约管理&#xff0c;场地使用管理 微信端账号功能包括&#xff1a;系统首页&#xff0c;场地信息&#xff0c;我的预约&a…

简易CPU设计入门:取指令(三),ip_buf与rd_en的非阻塞赋值

在开篇&#xff0c;还是请大家首先准备好本项目所用的源代码。如果已经下载了&#xff0c;那就不用重复下载了。如果还没有下载&#xff0c;那么&#xff0c;请大家点击下方链接&#xff0c;来了解下载本项目的CPU源代码的方法。 下载本项目代码 准备好了项目源代码以后&…

图形化编程-在DevC++中集成EasyX图形库

1、EasyX介绍 EasyX (EasyX Graphics Library)是针对 C/C++ 的图形库,可以帮助使用C/C++语言的程序员快速上手图形和游戏编程,可以用EasyX 很快的画一个房子,或者一辆移动的小车,也可以编写俄罗斯方块、贪吃蛇、黑白棋等小游戏,可以练习图形学的各种算法等等。 EasyX …

鸿蒙媒体开发系列15——图片解码(PixcelMap)

如果你也对鸿蒙开发感兴趣&#xff0c;加入“Harmony自习室”吧&#xff01;扫描下方名片&#xff0c;关注公众号&#xff0c;公众号更新更快&#xff0c;同时也有更多学习资料和技术讨论群。 1、概述 应用开发中的图片开发是对图片像素数据进行解析、处理、构造的过程&#x…

【Linux】Docker下载与使用-nginx

目录 一、Docker介绍 二、Docker结构 三、下载Daocker 1. 在linux上下载docker&#xff0c;执行以下命令即可&#xff1a; 2. 开启docker 3. 执行以下操作并进行使用 四、在Docker上安装nginx 一、Docker介绍 Docker&#xff1a;是给予Go语言实现的开源项…

开发者福音!一个小型热门项目,可以在线优雅快速生成 SQL 和模拟数据(带私活源码)

GitHub上开源了一个小型热门项目&#xff0c;可以在线快速生成SQL和模拟数据。 这对于前端开发的同学来说&#xff0c;简直是一大福音&#xff0c;可以大幅提升调试效率。 以后&#xff0c;再不用等后端同学开发完数据接口再进行下一步。 一起来看看吧&#xff01; 项目介绍…

react-问卷星项目(2)

流程 husky 一个git hook 工具&#xff0c;即在git commit之前执行自定义的命令&#xff0c;将规范流程化&#xff0c;如执行代码风格的检查&#xff0c;避免提交非规范的代码&#xff0c;在github搜索即可。 这两条是接着执行的&#xff0c;表示创建husky&#xff0c;在文档…

Linux系统安装和配置 VNC 服务器

文章目录 1.安装 GNOME 桌面环境2.安装 VNC 服务器&#xff08;tigervnc-server&#xff09;3.为本地用户设置 VNC 密码4.设置 VNC 服务器配置文件5.启动 VNC 服务并允许防火墙中的端口 1.安装 GNOME 桌面环境 [rootserver6 ~]# dnf groupinstall "workstation" -y成…