(58)先给出本节窗体的生成逻辑整理:

++介绍生成窗体的关键代码 ui_widget.h :

++上面的文件太大了,下图给出其成员函数:

++ 接着给出另一个重要的成员函数:

++给出本文件的源代码,彩色化效果没有 QT 的好,这会影响阅读效果。所以也是直接采用图片的原因:
/********************************************************************************
** Form generated from reading UI file 'widget.ui' 本源文件叫 UI_widget.h
**
** Created by: Qt User Interface Compiler version 6.2.4
**
** WARNING! All changes made in this file will be lost when recompiling UI file!
********************************************************************************/
#ifndef UI_WIDGET_H
#define UI_WIDGET_H
#include <QtCore/QVariant>
#include <QtWidgets/QApplication>
#include <QtWidgets/QGridLayout>
#include <QtWidgets/QLabel>
#include <QtWidgets/QPlainTextEdit>
#include <QtWidgets/QPushButton>
#include <QtWidgets/QSpinBox>
#include <QtWidgets/QVBoxLayout>
#include <QtWidgets/QWidget>
QT_BEGIN_NAMESPACE
class Ui_Widget
{
public: //本类有数据成员及两个成员函数,但没有构造函数与析构函数
QVBoxLayout * verticalLayout;
QGridLayout * gridLayout ;
QLabel * label ;
QLabel * label_2;
QSpinBox * spinBox_boy ;
QSpinBox * spinBox_girl;
QPushButton * bnBoyAdd ;
QPushButton * bnGirlAdd;
QPushButton * bnPrintMeta;
QPushButton * bnClearText;
QPlainTextEdit * plainTextEdit;
void setupUi(QWidget * Widget) //此形参就是本项目中的窗体对象
{ //const char * QMetaObject::className() const;
//QString QObject::objectName() const; 返回值不一样
if (Widget->objectName().isEmpty()) //bool QString::isEmpty() const
Widget->setObjectName(QString::fromUtf8("Widget"));
//void QObject::setObjectName(const QString &name);
//static QString fromUtf8(const char * utf8, qsizetype size)
Widget->resize(424, 253); //设置本窗体的大小、宽高
//class QLayout : public QObject, public QLayoutItem
//class QBoxLayout : public QLayout
//class QVBoxLayout : public QBoxLayout
//QVBoxLayout::QVBoxLayout(QWidget * parent);
verticalLayout = new QVBoxLayout(Widget); //此行设置了本窗体的垂直布局
verticalLayout->setObjectName(QString::fromUtf8("verticalLayout"));
//以下开始生成网格布局并填充之,并生成文本框,并全加入窗体的垂直布局
gridLayout = new QGridLayout();
gridLayout->setObjectName(QString::fromUtf8("gridLayout"));
label = new QLabel(Widget); //生成标签对象并加入网格布局
label->setObjectName(QString::fromUtf8("label"));//存储对象名
//void QGridLayout::addWidget(QWidget *, int row, int column,
// int rowSpan, int columnSpan, Qt::Alignment = Qt::Alignment());
gridLayout->addWidget(label, 0, 0, 1, 1);//rowSpan 指占据几行,列同
spinBox_boy = new QSpinBox(Widget); //生成螺旋框并加入网格布局
spinBox_boy->setObjectName(QString::fromUtf8("spinBox_boy"));
spinBox_boy->setValue(15);
gridLayout->addWidget(spinBox_boy, 0, 1, 1, 1);
bnBoyAdd = new QPushButton(Widget); //生成男增一按钮并加入网格布局
bnBoyAdd->setObjectName(QString::fromUtf8("bnBoyAdd"));
gridLayout->addWidget(bnBoyAdd, 0, 2, 1, 1);
bnPrintMeta = new QPushButton(Widget); //生成打印信息按钮并加入网格布局
bnPrintMeta->setObjectName(QString::fromUtf8("bnPrintMeta"));
gridLayout->addWidget(bnPrintMeta, 0, 3, 1, 1);
label_2 = new QLabel(Widget); //生成女标签并加入网格布局
label_2->setObjectName(QString::fromUtf8("label_2"));
gridLayout->addWidget(label_2, 1, 0, 1, 1);
spinBox_girl = new QSpinBox(Widget); //生成女螺旋框并加入网格布局
spinBox_girl->setObjectName(QString::fromUtf8("spinBox_girl"));
spinBox_girl->setValue(17);
gridLayout->addWidget(spinBox_girl, 1, 1, 1, 1);
bnGirlAdd = new QPushButton(Widget); //生成女增一按钮并加入网格布局
bnGirlAdd->setObjectName(QString::fromUtf8("bnGirlAdd"));
gridLayout->addWidget(bnGirlAdd, 1, 2, 1, 1);
bnClearText = new QPushButton(Widget); //生成清空按钮并加入网格布局
bnClearText->setObjectName(QString::fromUtf8("bnClearText"));
gridLayout->addWidget(bnClearText, 1, 3, 1, 1);
//将布局添加到盒子的末尾,使用序列拉伸因子拉伸。
//void QBoxLayout::addLayout(QLayout *layout, int stretch = 0);
verticalLayout->addLayout(gridLayout);//网格布局被添加入窗体的垂直布局
plainTextEdit = new QPlainTextEdit(Widget);//添加文本框入垂直布局
plainTextEdit->setObjectName(QString::fromUtf8("plainTextEdit"));
verticalLayout->addWidget(plainTextEdit);
//完成了上面的窗体布局后,由下面的函数填写与设置设置窗体上的可视化文本
retranslateUi(Widget);
QMetaObject::connectSlotsByName(Widget);//启用基于控件名的信号槽绑定
} // setupUi
void retranslateUi(QWidget *Widget)
{ //看内容是设置了 UI 界面上各控件的可视化名称,人们可以看到的控件名称
Widget ->setWindowTitle(QCoreApplication::translate("Widget", "\345\205\203\345\257\271\350\261\241\347\263\273\347\273\237\345\212\237\350\203\275\344\270\216\345\261\236\346\200\247\346\265\213\350\257\225", nullptr));
label ->setText(QCoreApplication::translate("Widget", "\350\256\276\347\275\256\347\224\267\347\224\237\345\271\264\351\276\204", nullptr));
bnBoyAdd ->setText(QCoreApplication::translate("Widget", "boy \351\225\277\345\244\247\344\270\200\345\262\201", nullptr));
bnPrintMeta->setText(QCoreApplication::translate("Widget", "\345\205\203\345\257\271\350\261\241\344\277\241\346\201\257", nullptr));
label_2 ->setText(QCoreApplication::translate("Widget", "\350\256\276\347\275\256\345\245\263\347\224\237\345\271\264\351\276\204", nullptr));
bnGirlAdd ->setText(QCoreApplication::translate("Widget", "girl \351\225\277\345\244\247\344\270\200\345\262\201", nullptr));
bnClearText->setText(QCoreApplication::translate("Widget", "\346\270\205\347\251\272\346\226\207\346\234\254", nullptr));
} // retranslateUi
};
namespace Ui { class Widget: public Ui_Widget {}; } // namespace Ui
QT_END_NAMESPACE
#endif // UI_WIDGET_H
(59),开始本项目中的源代码整理,先给出本项目的 qmake 文件:

++**给出头文件 tperson.h **,重新补充了头文件的注释,头文件中的注释更重要:

++给出头文件:

++给出源文件:

++ 源文件:

++ 开始给出另一个重要的源文件,生成窗体,完善信号与槽:

++以及构造函数:

++ 以及:

++ 以及:

++给出本源文件的完整代码:
#include "widget.h"
#include "ui_widget.h"
#include "tperson.h"
#include <QMetaProperty>
#include <QString>
Widget::~Widget() { delete ui; }
void Widget::on_bnBoyAdd_clicked()
{ ptrBoy->incAge();
// ui->spinBox_boy->setValue(ptrBoy->age());
}
void Widget::on_bnGirlAdd_clicked()
{ ptrGirl->incAge();
// ui->spinBox_girl->setValue(ptrGirl->age());
}
void Widget::on_bnClearText_clicked()
{ //清空文本框
ui->plainTextEdit->clear();
}
Widget::Widget(QWidget *parent) : QWidget(parent) , ui(new Ui::Widget)
{
ui->setupUi(this);
ptrBoy = new TPerson(this,"小明"); //这样就不用显式析构 TPerson 类型了
ptrBoy->setAge(ui->spinBox_boy->value()); //年龄与螺旋框保持一致
ptrBoy->setProperty("sex", "boy"); //定义了一个动态属性 sex
ptrBoy->setProperty("score", 99); //原来只有 name age score
ptrGirl = new TPerson(this,"小丽");
ptrGirl->setAge(ui->spinBox_girl->value());
ptrGirl->setProperty("sex", "girl");
ui->spinBox_boy ->setProperty("isBoy", true ); //此同名属性是为了区分
ui->spinBox_girl->setProperty("isBoy", false); //又一个动态属性
//void QSpinBox::valueChanged(int);实现由螺旋框引起的年龄改变逻辑
connect(ui->spinBox_boy, SIGNAL(valueChanged(int)),
this, SLOT(do_spinChanged(int)));
connect(ui->spinBox_girl,&QSpinBox::valueChanged,
this, &Widget::do_spinChanged);//修改年龄为螺旋框中的数据
connect(ptrBoy , SIGNAL(ageChanged(int)), //年龄改变后更新文本框
this, SLOT(do_ageChanged(int)));
connect(ptrGirl, &TPerson::ageChanged, //以下实施信号与槽的连接
this, &Widget::do_ageChanged); //本函联动文本框以更新学生信息
//void QSpinBox::valueChanged(int); 此函数是带形参的
//出现信号与槽函数的重载,则用 qOverload<int,char>(&A::func) 的方式
connect(ptrBoy , &TPerson::ageChanged, //这是后补充的
ui->spinBox_boy , &QSpinBox::setValue);
//void QSpinBox::setValue(int val);
connect(ptrGirl, &TPerson::ageChanged, //年龄改变后及时更新螺旋框
ui->spinBox_girl, &QSpinBox::setValue);
}
void Widget::do_ageChanged(int value) //本函作为 incage()的槽函数
{ //本函联动文本框以更新学生信息
//qobject_cast<T *> 相当于 c++ 的 dynamic_cast<T *>,仅此一个
TPerson * ptrPerson = qobject_cast<TPerson *>(sender());
QString name = ptrPerson->property("name").toString();
QString sex = ptrPerson->property("sex" ).toString();
int age = ptrPerson->age();
int score = ptrPerson->property("score").toInt();
QString str = QString("姓名:%1 ,性别:%2,年龄= %3,成绩= %4")
.arg(name).arg(sex).arg(age).arg(score);//%1 %2
ui->plainTextEdit->appendPlainText(str);
}
void Widget::do_spinChanged(int value) //本函作为 spinbox 的槽函数
{ //QObject * QObject::sender() const;
QSpinBox * ptrSpinbox = qobject_cast<QSpinBox *>(sender());
if(ptrSpinbox->property("isBoy").toBool()) //表示是男生
ptrBoy->setAge(value); //此函修正年龄后会触发新的信号与槽函数
else //QVariant QObject::property(const char * name) const;
ptrGirl->setAge(value);
}
void Widget::on_bnPrintMeta_clicked()
{ ui->plainTextEdit->clear();
ui->plainTextEdit->appendPlainText("类名称:");
const QMetaObject * ptrMetaObject = ptrBoy->metaObject();
//const char * QMetaObject::className() const;
ui->plainTextEdit->appendPlainText( ptrMetaObject->className() );
ui->plainTextEdit->appendPlainText("\n属性:");
for(int i = ptrMetaObject->propertyOffset();
i < ptrMetaObject->propertyCount() ; i++ )
{ //QMetaProperty QMetaObject::property(int index) const;
QMetaProperty objMetaProperty = ptrMetaObject->property(i);
const char * name = objMetaProperty.name();
//QVariant QObject::property(const char * name) const;
QVariant tmpVariant = ptrBoy->property(name);
// QString QVariant::toString() const;
QString strValue = tmpVariant.toString();
ui->plainTextEdit->appendPlainText(
QString("属性名:%1,属性值:%2").arg(name).arg(strValue) );
}
ui->plainTextEdit->appendPlainText("\n类信息(classInfo):");
//int QMetaObject::classInfoOffset() const;
for(int i = ptrMetaObject->classInfoOffset() ;
i < ptrMetaObject->classInfoCount () ; i++)
{ //QMetaClassInfo QMetaObject::classInfo(int index) const;
QMetaClassInfo objClassInfo = ptrMetaObject->classInfo(i);
ui->plainTextEdit->appendPlainText(
QString("类信息名:%1,类信息值:%2")
.arg(objClassInfo.name ()) //const char * QMetaClassInfo::name () const;
.arg(objClassInfo.value()) //const char * QMetaClassInfo::value() const;
);
}
}
(60)也一并给出前端界面的 搭建效果图,与控件对象的代码名称:

(61)
谢谢
3525

被折叠的 条评论
为什么被折叠?



