(19)纯代码化 UI 的初始文件组成:
++初始的窗体状态:
(20)本项目的代码文件汇总,先是对头文件做的修改:
++对应头文件的代码版:
#ifndef DIALOG_H
#define DIALOG_H
#include <QDialog>
#include <QCheckBox>
#include <QRadioButton>
#include <QPlainTextEdit>
#include <QPushButton>
//老师说:只有共用的系统头文件,才放到头文件里;
//.cpp 源文件也可以包含只有自己使用的头文件。
//故布局头文件 <QHBoxLayout>不再于此处包含。
//老师说也可以把此处的头文件包含换成类声明。
class Dialog : public QDialog
{
Q_OBJECT
private: //三个复选框、单选框、按钮、文本框。
QCheckBox * ptrChkbxUnderline, * ptrChkbxItalic, * ptrChkbxBold ;
QRadioButton * ptrRadioBnBlack , * ptrRadioBnBlue, * ptrRadioBnRed ;
QPlainTextEdit * ptrPlainTxtEdit;
QPushButton * ptrPushBnOK , * ptrPushBnQuit , * ptrPushBnCancel;
private slots: // MOC 新增的关键字 slots 表明是槽函数
void do_chkBoxUnder(bool checked);
void do_chkBoxItalic(bool checked);
void do_chkBoxBold(bool checked);
void do_setFontColor();
public:
void set_connect_signals_slots();
Dialog(QWidget *parent = nullptr);
~Dialog();
private:
};
#endif // DIALOG_H
++ 关于对 dialog.cpp 中 构造函数 Dialog::Dialog 的代码整理:
++对应此函数的代码版:
#include "dialog.h"
#include <QHBoxLayout>
#include <QVBoxLayout>
Dialog::Dialog(QWidget *parent) : QDialog(parent)
{ //QCheckBox(QString & text, QWidget * parent = nullptr);
ptrChkbxUnderline = new QCheckBox("下划线");
ptrChkbxItalic = new QCheckBox("斜体");
ptrChkbxBold = new QCheckBox("粗体");
//QRadioButton(QString &text, QWidget *parent = nullptr);
ptrRadioBnBlack = new QRadioButton("黑色");
ptrRadioBnBlue = new QRadioButton("蓝色");
ptrRadioBnRed = new QRadioButton("红色");
//QPlainTextEdit(QString &text, QWidget *parent = nullptr);
ptrPlainTxtEdit = new QPlainTextEdit("Qt6 手工创建");
//void QPlainTextEdit::setPlainText(const QString &text);
ptrPlainTxtEdit->setPlainText("Hello world\n 手工创建");
//const QFont & QWidget::font() 无法直接修改原对象里的字体
QFont myFont = ptrPlainTxtEdit->font();
//void QFont::setPointSize(int);使用点(逻辑单位)
//void QFont::setPixelSize(int) 使用像素(物理单位)
myFont.setPointSize(20);
//void QWidget::setFont(const QFont &);
ptrPlainTxtEdit->setFont(myFont);
//QPushButton(QString &text, QWidget *parent = nullptr);
ptrPushBnOK = new QPushButton("确定");
ptrPushBnCancel = new QPushButton("取消");
ptrPushBnQuit = new QPushButton("退出");
//class QHBoxLayout : public QBoxLayout : public QLayout
// public QLayout : public QObject, public QLayoutItem
QHBoxLayout * ptrHboxLayoutFont = new QHBoxLayout();
//void QBoxLayout::addWidget(QWidget *, int stretch = 0,
// Qt::Alignment alignment = Qt::Alignment());参数太长而换行
ptrHboxLayoutFont->addWidget(ptrChkbxUnderline);
ptrHboxLayoutFont->addWidget(ptrChkbxItalic);
ptrHboxLayoutFont->addWidget(ptrChkbxBold);
QHBoxLayout * ptrHboxLayoutColor = new QHBoxLayout();
ptrHboxLayoutColor->addWidget(ptrRadioBnBlack);
ptrHboxLayoutColor->addWidget(ptrRadioBnBlue);
ptrHboxLayoutColor->addWidget(ptrRadioBnRed);
QHBoxLayout * ptrHboxLayoutPushBn = new QHBoxLayout();
//void QBoxLayout::addStretch(int stretch = 0);带缩放因子的弹性空白
ptrHboxLayoutPushBn->addStretch();
ptrHboxLayoutPushBn->addWidget(ptrPushBnOK);
ptrHboxLayoutPushBn->addWidget(ptrPushBnCancel);
ptrHboxLayoutPushBn->addStretch(); //加入空白占位
ptrHboxLayoutPushBn->addWidget(ptrPushBnQuit);
QVBoxLayout * ptrVboxLayout = new QVBoxLayout();
//void QBoxLayout::addLayout(QLayout *layout, int stretch = 0);
ptrVboxLayout->addLayout(ptrHboxLayoutFont);
ptrVboxLayout->addLayout(ptrHboxLayoutColor);
ptrVboxLayout->addWidget(ptrPlainTxtEdit);//仍来源于QBoxLayout
ptrVboxLayout->addLayout(ptrHboxLayoutPushBn);
//void QWidget::setLayout(QLayout *);
setLayout(ptrVboxLayout); //设置本对话框窗体的布局
//void QWidget::setWindowTitle(const QString &);
setWindowTitle("手工打造 UI");
set_connect_signals_slots(); //主要为了拆分太长的函数,以便整理源码
} //QT 扩展了c++的功能,根类窗体析构时候会析构窗体里的所有控件以避免内存泄露
++ 给出源文件的 框架:
++ 给出 成员函数 void Dialog::set_connect_signals_slots ( ) 的实现:
++ 给出其源代码版本:
void Dialog::set_connect_signals_slots()
{ // 设置字体、颜色、以及三个按钮
connect(ptrChkbxUnderline, SIGNAL(clicked(bool)),
this, SLOT(do_chkBoxUnder(bool)));
connect(ptrChkbxItalic, SIGNAL(clicked(bool)),
this, SLOT(do_chkBoxItalic(bool)));
connect(ptrChkbxBold, SIGNAL(clicked(bool)),
this, SLOT(do_chkBoxBold(bool)));
connect(ptrRadioBnBlack, SIGNAL(clicked(bool)),
this, SLOT(do_setFontColor()));
connect(ptrRadioBnBlue, SIGNAL(clicked(bool)),
this, SLOT(do_setFontColor()));
connect(ptrRadioBnRed, SIGNAL(clicked(bool)),
this, SLOT(do_setFontColor()));
connect(ptrPushBnOK, SIGNAL(clicked()),
this, SLOT(accept())); //同意对话框
connect(ptrPushBnCancel, SIGNAL(clicked()),
this, SLOT(reject())); //拒绝对话框
connect(ptrPushBnQuit, SIGNAL(clicked()),
this, SLOT(close())) ; //关闭对话框
}
++ 给出槽函数的定义:
++给出其源代码版本:
void Dialog::do_chkBoxUnder(bool checked)
{
QFont myFont = ptrPlainTxtEdit->font();
myFont.setUnderline(checked);
//void QWidget::setFont(const QFont &);
ptrPlainTxtEdit->setFont(myFont);
}
void Dialog::do_chkBoxItalic(bool checked)
{
QFont myFont = ptrPlainTxtEdit->font();
myFont.setItalic(checked);
ptrPlainTxtEdit->setFont(myFont);
}
void Dialog::do_chkBoxBold(bool checked)
{
QFont myFont = ptrPlainTxtEdit->font();
myFont.setBold(checked);
ptrPlainTxtEdit->setFont(myFont);
}
void Dialog::do_setFontColor()
{ // const QPalette & QWidget::palette() const;
QPalette myPalette = ptrPlainTxtEdit->palette();
// void QPalette::setColor(ColorRole acr, const QColor &acolor)
// { setColor(All, acr, acolor); }
if(ptrRadioBnBlack->isChecked())
myPalette.setColor(QPalette::Text, Qt::black);
else if(ptrRadioBnBlue->isChecked())
myPalette.setColor(QPalette::Text, Qt::blue);
else if(ptrRadioBnRed->isChecked())
myPalette.setColor(QPalette::Text, Qt::red);
//void setPalette(const QPalette &);
ptrPlainTxtEdit->setPalette(myPalette);
}
(21) SIGNAL、SLOT、signals、slots、emit 关键字含义 ,谢谢这位大师:
SIGNAL、SLOT
源码路径:/home/(name)/Qt5.14.2/5.14.2/Src/qtbase/src/corelib/kernel/qobjectdefs.h
Q_CORE_EXPORT const char *qFlagLocation(const char *method);
#ifndef QT_NO_META_MACROS
#ifndef QT_NO_DEBUG // Debug
#define QLOCATION "\0" __FILE__ ":" QT_STRINGIFY(__LINE__)
#ifndef QT_NO_KEYWORDS
#define METHOD(a) qFlagLocation("0" #a QLOCATION)
#endif
#define SLOT(a) qFlagLocation("1" #a QLOCATION)
#define SIGNAL(a) qFlagLocation("2" #a QLOCATION)
#else // Release
#ifndef QT_NO_KEYWORDS // else 分支的意思就是定义了宏 QT_NO_DEBUG,即 release 版本
#define METHOD(a) "0" #a
#endif
#define SLOT(a) "1" #a
#define SIGNAL(a) "2" #a
#endif
#define QMETHOD_CODE 0 // member type codes
#define QSLOT_CODE 1
#define QSIGNAL_CODE 2
#endif // QT_NO_META_MACROS
++由上述代码可知,关键字 SIGNAL 和 SLOT 实际上是两个宏,其功能均是将信号函数和槽函数字符串化并在前面加上标识符:1或者2,以用来区分槽和信号。
在 Debug 模式下,上述字符串中还会加入文件名和行号,用以在信号槽出错时输出响应的调试信息。
二、signals、slots、emit
源码路径:/home/(name)/Qt5.14.2/5.14.2/Src/qtbase/tests/auto/tools/moc/no-keywords.h
#define signals Q_SIGNALS
#define slots Q_SLOTS
#define emit Q_EMIT
++接着,我们查找后几个宏的定义来源:
源码路径:/home/(name)/Qt5.14.2/5.14.2/Src/qtbase/src/corelib/kernel/qobjectdefs.h
#ifndef QT_ANNOTATE_ACCESS_SPECIFIER // annotate 是注释的意思
#define QT_ANNOTATE_ACCESS_SPECIFIER(x)
#endif
...
#define Q_SLOTS QT_ANNOTATE_ACCESS_SPECIFIER(qt_slot)
#define Q_SIGNALS public QT_ANNOTATE_ACCESS_SPECIFIER(qt_signal)
#define Q_EMIT
++虽然如此,如此重要的宏,居然定义为空,作为 MOC 编译器里的关键字, signals slots emit ,还是要使用的,否则会报错。
(22)从头文件的函数定义到源文件的函数生成:
(23)
谢谢