前言:

我可没说放弃

Base class中的三个选项:
QMainWindow:主窗口类,包括菜单栏、工具栏、状态栏。
QWidget:可以创建一个空白的窗口,是所有界面组件的基类。
QDialog:对话框类。

Clang代码模型:
help->About Plugins…->C++->ClangCodeModel去掉勾选,再重启
会对源码进行分析,提供函数提示、代码补全等功能
会出现大量警告和错误提示
可以在Help->About Plugins中取消了该项(ClangCodeModel)

qmake是构建项目的软件,它根据.pro文件生成Makefile文件,然后C++编译器可以根据Makefile文件进行编译和链接
qmake还会自动生成MOC(meta-object compiler)和UIC(user interface compiler)生成构建规则
$$为替换函数的前缀

//Qt框架中的模块分为两大类:
-Qt 基本模块(Qt Essentials):提供了 Qt 在所有平台上的基本功能。
-Qt 附加模块(Qt Add-Ons):实现一些特定功能的模块。
基本模块:
Qt Core           //Qt框架的核心,定义了元对象系统
Qt GUI           //设计 GUI 界面的基础类,包括事件处理、文字处理等
Qt Widgets       //提供用于创建GUI的各种界面组件类
Qt D-Bus         //D-Bus是实现进程间通信(inter process communication,IPC)和远程过程调用(remote procedure call,RPC)的一种通信协议
Qt Test          //提供一些对应用程序和库进行单元测试的类
Qt QML           //提供用QML编程的框架,定义了QML和基础引擎
Qt Quick         //用于开发QML应用程序的标准库,提供创建UI的一些基本类型
Qt Quick Controls//提供一套基于Qt Quick的控件,可用于创建复杂的UI
Qt Quick Dialogs //提供通过QML使用系统对话框的功能
Qt Quick Layouts //提供用于管理界面布局的QML类型
Qt Quick Test    //提供QML应用程序的单元测试框架
其他模块:
自行添加。

//Qt的元对象系统
1. 元对象(meta object):每个QObject及其子类的实例都有一个元对象(静态变量staticMetaObject)。函数metaObject()可以返回它的指针。
2. 类型信息:QObject的inherits()函数可以判断继承关系。
3. 动态翻译:函数tr()返回一个字符串的翻译版本。
4. 对象树:表示对象间从属关系的树状结构。QObject提供了parent()、children()、findChildren()等函数。对象树中的某个对象被删除时,它的子对象也将被删除。
5. 信号和槽:对象间的通信机制。
6. 属性系统:可以使用宏Q_PROPERTY定义属性,QObject的setProperty()会设置属性的值或定义动态属性;property函数会返回属性的值。


//信号和槽:
最后一个参数:Qt::ConnectionType表示了信号与槽槽之间的关联方式
Qt::AutoConnection(缺省值):自动确定关联方式。
Qt::DirectConnection:信号被发射时,槽立即执行,槽函数与信号在同一线程
Qt::QueuedConnection:事件循环回到接收者线程后执行槽,槽与信号在不同线程
Qt::BlockingQueueConnection:与Qt::QueuedConnection相似,信号线程会被阻塞直到槽执行完毕。当槽函数与信号在同一线程,会造成死锁。
//disconnect()函数的使用
1. 解除与一个sender所有signal的连接:
disconnect(myObject,nullptr,nullptr,nullptr);//静态函数
myObject->disconnect();      
2. 解除与一个特定信号的所有连接:
disconnect(myObject, SIGNAL(mySignal()), nullptr, nullptr); 
myObject->disconnect(SIGNAL(mySignal()));
3. 解除与一个特定receiver的所有连接:
 disconnect(myObject, nullptr, myReceiver, nullptr);
4. 解除一对特定的信号和槽的连接:
 myObject->disconnect(myReceiver);
disconnect(lineEdit, &QLineEdit::textChanged,label, &QLabel::setText);
//(sender)函数     
在槽函数里,使用QObject::sender()可以获取信号发射者的指针
QSpinBox * spinbox = qobject_cast<QSpinBox *>(sender());


//QVariant
各种属性的数据类型不同,需要使用QVariant类表示可以存储任何类型的数据。
QVariant var(173); 
QString str=var.toString();     //str="173"
int val=var.value<int>();       //val=173

QStringList strList;
strList<<"one"<<"two"<<"three";
var.setValue(strList);                  //给var赋值一个字符串列表
QStringList value=var.toStringList();   //转换为字符串列表

QFont font=this->font();        //窗口的字体
QVariant var=font;              //赋值给一个QVariant变量
QFont font2=var.value<QFont>(); //转换为QFont类型

//QRandomGenerator
QRandomGenerator *rand1=new QRandomGenerator(QDataTime::currentMSecsSinceEpoch());
QRandomGenerator *rand2=new QRandomGenerator(QDataTime::currentMSecsSinceEpoch());
for(int i=0;i<5;i++)
    qDebug("R1=%u,R2=%u",rand1->generate(),rand2->generate());

QRandomGenerator rand(QDateTime::currentSecsSinceEpoch());
for(int i=0;i<5;i++)
    qDebug("number=%u",rand());//rand()等同于rand.generate()

QList<quint32> list;
list.resize(16);
QRandomGenerator::global()->fillRange(list.data(), list.size());

quint32 array[10];
QRandomGenerator::global()->fillRange(array);//生成随机数并填充数组

double QRandomGenerator::bounded(double highest)
quint32 QRandomGenerator::bounded(quint32 highest)
quint32 QRandomGenerator::bounded(quint32 lowest, quint32 highest)
int QRandomGenerator::bounded(int highest)
int QRandomGenerator::bounded(int lowest, int highest)
quint64 QRandomGenerator::bounded(quint64 highest)

要获得[60,101)之间的值,可以这样写:
quint32 v = QRandomGenerator::global()->bounded(60, 101);



1. 日期时间:QTimeEdit,QDateEdit,QDateTimeEdit、QCalendarWidget。

2. QTimer是软件定时器,QTimer的主要功能是设置一个以毫秒为单位的定时周期,然后进行连续定时或单次定时。
QTimer::singleShot静态函数,可以方便的调用一次slot函数
QElapsedTimer用于快速计算两个事件之间的间隔时间,是软件计时器。

enum Qt::TimerType,有3个值:
Qt::PreciseTimer:value为0,精度保持在毫秒级别
Qt::CoarseTimer:value为1,精度保持在所需间隔的5%以内
Qt::VeryCoarseTimer:value为2,非常粗糙的定时器,精度保持在秒级

3. QComboBox是下拉列表框组件,它提供一个下拉列表供用户选择输入,也可以提供一个编辑框用于输入文字。ComboBox下拉列表的每个项(item)还可以存储一个或多个QVariant类型的用户数据,用户数据并不显示在界面上。

4. QListWidget是显示的列表组件,列表的每个项是一个QListWidgetItem对象,一个项存储了文字、图标、用户数据等内容。

5. QToolButton类
setDefaultAction()函数,可以与Action关联。
通过popupMode属性描述如何弹出菜单。
enum ToolButtonPopupMode { DelayedPopup, MenuButtonPopup, InstantPopup }

6. Qt 中用于项(Item)处理的组件有两类:
Item Views:包括 QListView、QTreeView、 QTableView、QColumnView 等;(父类)
Item Widgets:包括 QListWidget、QTreeWidget 和 QTable Widget;(子类)
7. QTreeWidget是一种Item Widget组件,即树形组件,它的项(item)被称为节点。树形组件适合于显示具有层级结构的数据。

8. QTableWidget是一种Item Widget组件,它以表格形式显示和管理数据。表格的每个单元格关联一个QTableWidgetItem对象,可以设置每个单元格的文字内容、字体、文字颜色、背景色、图标等,还可以有复选框。每个单元格还可以存储用户数据。

9. QSlider和QProgressBar
QProgressBar的format属性类型为QString,其中占位符含义如下:
%p ,完成的百分比
%v ,当前值
%m,总步数
默认值为“%p%”。

代码参考:

知识点:
1. ui_widget.h:类的名称是Ui_widget.h,根据组件、信号与信号槽自动生成。
2. 数学运算函数在 <QtMath> 头文件中定义
3. 消息显示: qDebug,qWarning、qCritical、qFatal、qInfo 
4. 全局宏:QT_VERSION、QT_VERSION_STR、
5. 容器:QList、QStack和QQueue;QMap、QMultiMap、QHash、QMultiHash和QSet。
6. QGridLayout类添加组件的函数是addWidget():
7. QAbstractButton的autoExclusive属性:如果启用了自动独占性,属于同一个父部件的可检查按钮将互斥。
8. QGroupBox的flat属性:可以最小化区域框的空间消耗。在大多数样式中,启用这个属性会移除框架的左边缘、右边缘和底边。



代码:
1. main.cpp
QPushButton* btn = new QPushButton("zhouyi",&w);
2. 一个信号可以连接多个槽函数
ui->setupUi(this);
connect(ui->radioBlack,SIGNAL(clicked()),this,SLOT(do_setFontColor()));
connect(ui->radioBlue,SIGNAL(clicked()),this,SLOT(do_setFontColor()));
connect(ui->radioRed,SIGNAL(clicked()),this,SLOT(do_setFontColor()));
3. Q_UNUSED(name)//这个宏用于在函数中定义不在函数体里使用的参数
void MainWindow::on_imageSaved(int id, const QString &fileName) 
{ 
Q_UNUSED(id); 
LabInfo->setText ("图片保存为:"+ fileName); 
}
4. 布局分布管理 stretch
layoutStretch:0,0,0,表示3个组件平均分配宽度
layoutStretch:0,0,1,表示前两个组件达到合适宽度后不再增加宽度,其余的空间都分配给第三个组件
layoutStretch:1,1,2,表示前两个组件达到合适宽度后将尽量满足1:1:2的比例
5. 分割条允许用户通过拖动子widget之间的边界来控制子widget的大小。
QSplitter *splitter = new QSplitter(parent);
QListView *listview = new QListView;
QTreeView *treeview = new QTreeView;
QTextEdit *textedit = new QTextEdit;
splitter->addWidget(listview);
splitter->addWidget(treeview);
splitter->addWidget(textedit);
//splitter->setOrientation(Qt::Vertical);





999. QMetaObject类
int main(int argc, char *argv[]){
    QApplication a(argc, argv);
    //QObject::metaObject返回类关联的元对象
    QObject *btn = new QPushButton;
    qDebug()<<btn->metaObject()->className(); //返回“QPushButton”
    QPushButton *btnPush=qobject_cast<QPushButton*>(btn);//qobject_cast类似于标准C++中的dynamic_cast
    qDebug()<<btnPush->metaObject()->className();
    QTimer *timer = new QTimer();               //QTimer是QObject的子类
    qDebug()<<timer->inherits("QTimer");        //返回true
    qDebug()<<timer->inherits("QObject");       //返回true
    qDebug()<<timer->inherits("QAbstrctButton");//返回false
    //superClass返回父类的元对象
    qDebug()<<btn->metaObject()->superClass()->className();
}
1000:属性系统:
Q_PROPERTY(bool focus READ hasFocus) 
Q_PROPERTY(bool enabled READ isEnabled WRITE setEnabled) 
Q_PROPERTY(QCursor cursor READ cursor WRITE SetCursor RESET unsetCursor) 
int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    QPushButton *button = new QPushButton;
    QObject *object = button;
    bool isFlat = object->property("flateee").toBool();
    qDebug()<<isFlat;
    object->setProperty("flateee",true);
    isFlat = object->property("flateee").toBool();
    qDebug()<<isFlat;
    const QMetaObject *meta=object->metaObject();
    int index=meta->indexOfProperty("down");
    QMetaProperty prop=meta->property(index);
    bool res=prop.isWritable();
    qDebug()<<" down(QPushButton) isWritable?: "<<res;
}
1001:类的附加信息
Q_OBJECT 
Q_CLASSINFO("author","Wang") 
Q_CLASSINFO("compay","UPC")
Q_CLASSINFO("version","3.0.1")

QMyWidget * myWidget = new QMyWidget;
qDebug()<<myWidget->metaObject()->classInfo(0).name();
qDebug()<<myWidget->metaObject()->classInfo(0).value(); 
qDebug()<<myWidget->metaObject()->classInfo(1).name(); 
qDebug()<<myWidget->metaObject()->classInfo(1).value();
1002. 自定义信号及其使用:
class QPerson:public QObject 
{ 
Q_OBJECT 
private: 
int m_age = 10; 
public: 
void incAge(); 
signals: 
void ageChanged(int value); 
}; 
void QPerson::incAge() { m_age++; emit ageChanged(m_age); //发射信号 
1003:容器:
QList<float> list; //定义一个float类型的数据列表
QList<int> list={1,2,3,4,5};//初始化列表数据
QList<int> list(100); //初始化列表元素个数为100,所有元素默认为0
QList<QString> strList(10,"pass");//10个元素,每个元素都被初始化为pass
QList<QString> list;
list<<"Monday"<<"Tuesday"<<"Wednesday"<<"Thursday";
list.append("Friday");
QString str1=list[0];        	//QList::const_reference QList::operator[](qsizetype i) const
QString str2=list.at(1);  
//------------
QMap<QString, int> map;
map["one"] = 1;
map["three"] = 3;
map["seven"] = 7
map.insert("twelve", 12);
int num1 = map["one"];
//如果在map中没有指定键的项,这些函数返回一个默认构造的值。
int num2 = map["thirteen"];
int num3 = map.value("thirteen");
//还有一个value()重载方法,如果指定的键不存在,则使用第二个参数作为默认值
 int num4 = map.value("thirteen",13);
5. foreach
QList<QString> values;
foreach (QString str, values)
    qDebug() << str;