QT5笔记:7. 自定义类、自定义信号及类的元对象信息

  • 自定义的QPerson类,需要继承 QObject类

    • qperson.h头文件

      #ifndef QPERSON_H
      #define QPERSON_H
      #include <QObject>
      class QPerson : public QObject
      {
      Q_OBJECT
      Q_CLASSINFO("author", "……");
      Q_CLASSINFO("company", "……");
      Q_CLASSINFO("version", "1.0");
      Q_PROPERTY(unsigned int age READ age WRITE setAge NOTIFY ageChanged);
      Q_PROPERTY(QString name MEMBER m_name);
      Q_PROPERTY(int score MEMBER m_score);
      public:
      explicit QPerson(QString name, QObject *parent = nullptr);
      unsigned int age();
      void setAge(unsigned int val);
      void increaseAge();
      private:
      unsigned int m_age = 10;
      QString m_name;
      int m_score = 80;
      signals:
      void ageChanged(int age);//自定义的信号
      };
      #endif // QPERSON_H
    • qperson.cpp 类文件

      #include "qperson.h"
      QPerson::QPerson(QString name, QObject *parent) : QObject(parent)
      {
      m_name = name;
      }
      unsigned int QPerson::age()
      {
      return m_age;
      }
      void QPerson::setAge(unsigned int val)
      {
      if (val != m_age)//当变化时设置值并发射信号
      {
      m_age = val;
      emit(ageChanged(m_age));//发射信号
      }
      }
      void QPerson::increaseAge()
      {
      m_age++;
      emit(ageChanged(m_age));//发射信号
      }
    • widget.h 界面的头文件

    #ifndef WIDGET_H
    #define WIDGET_H
    #include <QWidget>
    #include "qperson.h" //自己创建的类,用双引号引入
    QT_BEGIN_NAMESPACE
    namespace Ui
    {
    class Widget;
    }
    QT_END_NAMESPACE
    class Widget : public QWidget
    {
    Q_OBJECT
    public:
    Widget(QWidget *parent = nullptr);
    ~Widget();
    private slots: //信号&槽不同于方法,需要写在头文件的这里 private slots
    void on_btnAddBoyAge_clicked();
    void on_btnAddGirlAge_clicked();
    void on_btnMetaInfo_clicked();
    void on_spin_valueChanged(int val);
    void on_ageChanged(int age);
    private:
    Ui::Widget *ui;
    QPerson *boy;
    QPerson *girl;
    };
    #endif // WIDGET_H
    • widget.cpp 界面的类文件
    #include "widget.h"
    #include "ui_widget.h"
    #include <QMetaProperty>
    Widget::Widget(QWidget *parent)
    : QWidget(parent), ui(new Ui::Widget)
    {
    ui->setupUi(this);
    ui->spinBoxBoyAge->setProperty("isBoy", true);// 类似于WinForm 的Tag,但是比Tag强大,键值对类型
    ui->spinBoxGirlAge->setProperty("isBoy", false);
    boy = new QPerson("张三");
    boy->setAge(12);
    boy->setProperty("score", 99);
    boy->setProperty("sex", "boy"); //动态属性
    // connect(boy, &QPerson::ageChanged, this, &Widget::on_ageChanged);
    connect(boy, SIGNAL(ageChanged(int)), this, SLOT(on_ageChanged(int)));//链接自定义函数
    girl = new QPerson("蕾欧娜");
    girl->setAge(15);
    girl->setProperty("score", 120);
    girl->setProperty("sex", "girl"); //动态属性
    connect(girl, SIGNAL(ageChanged(int)), this, SLOT(on_ageChanged(int)));
    connect(ui->spinBoxBoyAge, SIGNAL(valueChanged(int)), this, SLOT(on_spin_valueChanged(int)));
    connect(ui->spinBoxGirlAge, SIGNAL(valueChanged(int)), this, SLOT(on_spin_valueChanged(int)));
    }
    Widget::~Widget()
    {
    delete ui;
    }
    void Widget::on_btnAddBoyAge_clicked()
    {
    boy->increaseAge();
    }
    void Widget::on_btnAddGirlAge_clicked()
    {
    girl->increaseAge();
    }
    /**
    * @brief Widget::on_btnMetaInfo_clicked 元对象信息:对象信息和类的信息
    */
    void Widget::on_btnMetaInfo_clicked()
    {
    ui->textBoxInfo->clear();
    const QMetaObject *metaGirl = girl->metaObject();
    ui->textBoxInfo->appendPlainText("【对象信息】");
    ui->textBoxInfo->appendPlainText(QString("类名称:%1").arg(metaGirl->className()));
    QString text = QString::Null();
    for (int i = metaGirl->propertyOffset(); i < metaGirl->propertyCount(); i++)//属性的获取方式
    {
    QMetaProperty property = metaGirl->property(i);
    const char *name = property.name();
    QString value = girl->property(name).toString();
    text += QString("属性名:%1").arg(name) + "\t值:" + value + "\n";//字符串的拼接
    }
    ui->textBoxInfo->appendPlainText(text);
    ui->textBoxInfo->appendPlainText("【类信息】");
    QString classInfo = QString::Null();
    for (int i = metaGirl->classInfoOffset(); i < metaGirl->classInfoCount(); i++)
    {
    QMetaClassInfo classInf = metaGirl->classInfo(i);
    const char *name = classInf.name();
    const char *value = classInf.value();
    classInfo += QString("属性名:%1\t值:%2\n").arg(name).arg(value);//格式化字符串拼接函数
    }
    ui->textBoxInfo->appendPlainText(classInfo);
    }
    void Widget::on_spin_valueChanged(int val)
    {
    Q_UNUSED(val);//标明这个变量unused
    QSpinBox *box = qobject_cast<QSpinBox *>(sender());//类似于WinForm 的事件里的sender,一样需要类型转换,并且类型不匹配时返回null
    if (box->property("isBoy").toBool())
    boy->setAge(box->value());
    else
    girl->setAge(box->value());
    }
    void Widget::on_ageChanged(int age)
    {
    Q_UNUSED(age);//标明这个变量unused
    QPerson *person = qobject_cast<QPerson *>(sender());
    QString name = person->property("name").toString();
    QString sex = person->property("sex").toString();
    unsigned int p_age = person->age();
    ui->textBoxInfo->appendPlainText("姓名:" + name + " ,性别:" + sex + ", 年龄:" + QString::asprintf("%d", p_age));//格式化输出
    if (person->property("sex").toString() == "boy")
    ui->spinBoxBoyAge->setValue(p_age);
    else
    ui->spinBoxGirlAge->setValue(p_age);
    }
    • 最终界面样式
      image

__EOF__

本文作者echo_lovely
本文链接https://www.cnblogs.com/echo-lovely/p/17219246.html
关于博主:评论和私信会在第一时间回复。或者直接私信我。
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
声援博主:如果您觉得文章对您有帮助,可以点击文章右下角推荐一下。您的鼓励是博主的最大动力!
posted @   echo_lovely  阅读(293)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 全程不用写代码,我用AI程序员写了一个飞机大战
· DeepSeek 开源周回顾「GitHub 热点速览」
· 记一次.NET内存居高不下排查解决与启示
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
点击右上角即可分享
微信分享提示