一、简介
1.1 什么是Qt
Qt是一个跨平台的C++图形用户界面应用程序框架。它为应用程序开发者提供建立艺术级图形界面所需的所有功能。它是完全面向对象的,很容易扩展,并且允许真正的组件编程。
Qt框架除了QML和Qt Creator外,还包括多个重要的组件和工具,如:
- Qt Designer:用于可视化设计Qt Widgets窗口UI界面,支持拖放控件和布局,自动生成C++代码。
- Qt Linguist:用于应用程序的国际化,支持翻译Qt应用程序中的字符串。
- Qt Assistant:提供Qt框架的文档浏览器,帮助开发人员快速查找API文档和教程。
- qmake:Qt的构建系统,用于自动化生成Makefile文件,简化编译过程。
- Qt Quick Designer(在Qt Design Studio中):专门用于设计Qt Quick应用程序的可视化工具。
Qt的优点
- 跨平台,几乎支持所有的平台
- 接口简单,容易上手,学习QT框架对学习其他框架有参考意义。
- 一定程度上简化了内存回收机制
- 开发效率高,能够快速的构建应用程序。
- 有很好的社区氛围,市场份额在缓慢上升。
- 可以进行嵌入式开发。
Qt成功案例
- Linux桌面环境 KDE
- WPS Office 办公软件
- Skype 网络电话
- Google Earth 谷歌地图
- VLC多媒体播放器
- VirtualBox虚拟机软件
1.2 什么是 Qt Creator
Qt Creator是一个跨平台的集成开发环境(IDE),专为使用Qt框架进行应用程序开发而设计。它支持在Linux、macOS和Windows操作系统上运行,帮助开发者为桌面、移动端和嵌入式平台创建软件。(当前教程)
1.3 什么是qml
- QML(Qt Meta-Object Language):是Qt Quick技术的一部分,一种声明式编程语言,用于描述用户界面。QML允许开发者以简洁的方式定义用户界面,同时支持与Qt原生C++代码的交互。之后会详细做笔记。
1.4 什么是minGW
MinGW(Minimalist GNU for Windows)是Qt下的一种编译器工具链,它将经典的开源C/C++编译器GCC移植到了Windows平台,并包含了Win32API,允许开发者在Windows环境下使用GNU工具链进行开发和构建,生成Windows下的可执行程序。MinGW是开源免费的,生成的软件遵循GNU开源许可协议,适合用于跨平台开发或偏好开源工具链的项目。在Qt中,MinGW与MSVC是两种常用的编译方式,它们各有特点,开发者可以根据项目需求和个人偏好选择使用。
2、下载地址
1、官网下载: Index of /official_releases/online_installers
2、其它方法:
关注微信号:Qt君
网盘:链接:https://pan.baidu.com/s/1DaHmaEmh-Bn31TMlKs9Hww
提取码:1i13
3、配置编译套件
b、默认安装是minGW,如需msvc需要安装2015版本的,如果是其它版本的vs编译器,需要进行相关配置,作者qt是5.12版本的,msvc是2017的, 如下
首先克隆图中选中的 c编译器,接着进行相关配置,msvc版本是多少位的就选多少位,这里我的是msvc2017 32位版本的,配置如下,名字可以更改。
c++编译器也要进行相关配置,好了之后如下:
之后把刚刚配置好的编译器配置到构建套件中,就可以了
4、相关文件简介
补充:
创建工程时最好不要有中文路径或者中文名字,可能会有未定义行为
.pro文件
.pro就是工程文件(project),它是qmake自动生成的用于生产makefile的配置文件。
.pro文件的写法如下:
注释 从“#”开始,到这一行结束
- 模板变量告诉qmake为这个应用程序生成哪种makefile。下面是可供使用的选择:TEMPLATE = app
- app -建立一个应用程序的makefile。这是默认值,所以如果模板没有被指定,这个将被使用。
- lib - 建立一个库的makefile。
- vcapp - 建立一个应用程序的VisualStudio项目文件。
- vclib - 建立一个库的VisualStudio项目文件。
- subdirs -这是一个特殊的模板,它可以创建一个能够进入特定目录并且为一个项目文件生成makefile并且为它调用make的makefile。#指定生成的应用程序名:
TARGET = QtDemo
- #工程中包含的头文件
HEADERS += include/painter.h
- #工程中包含的.ui设计文件
FORMS += forms/painter.ui
- #工程中包含的源文件
SOURCES += sources/main.cpp sources
- #工程中包含的资源文件
RESOURCES += qrc/painter.qrc
- greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
这条语句的含义是,如果QT_MAJOR_VERSION大于4(也就是当前使用的Qt5及更高版本)需要增加widgets模块。如果项目仅需支持Qt5,也可以直接添加“QT += widgets”一句。不过为了保持代码兼容,最好还是按照QtCreator生成的语句编写。
#配置信息
CONFIG用来告诉qmake关于应用程序的配置信息。
CONFIG += c++11 //使用c++11的特性
在这里使用“+=”,是因为我们添加我们的配置选项到任何一个已经存在中。这样做比使用“=”那样替换已经指定的所有选项更安全。
解释:
- Qt系统提供的标准类名声明头文件没有.h后缀
- Qt一个类对应一个头文件,类名就是头文件名
- QApplication应用程序类
- 管理图形用户界面应用程序的控制流和主要设置。
- 是Qt的整个后台管理的命脉它包含主事件循环,在其中来自窗口系统和其它资源的所有事件处理和调度。它也处理应用程序的初始化和结束,并且提供对话管理。
- 对于任何一个使用Qt的图形用户界面应用程序,都正好存在一个QApplication 对象,而不论这个应用程序在同一时间内是不是有0、1、2或更多个窗口。
- a.exec()
程序进入消息循环,等待对用户输入进行响应。这里main()把控制权转交给Qt,Qt完成事件处理工作,当应用程序退出的时候exec()的值就会返回。在exec()中,Qt接受并处理用户和系统的事件并且把它们传递给适当的窗口部件。
运行效果如下开始学习把!!!
5、qt项目转vs
增加qmake环境
使用cmd命令 :qmake -tp vc filename.pro //注意: filenam为你的文件名字
二、基础
1、常用控件
QPushbutton (按钮)
代码如下:
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include<QPushButton>
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::MainWindow)
{
ui->setupUi(this);
this->setFixedSize(400,300); //设置主窗口尺寸
this->setWindowTitle("Hell Qt");
//创建按钮1
QPushButton *pushBUtton1=new QPushButton("pushBUtton1",this);
pushBUtton1->setGeometry(10,10,100,30); //设置位置和大小
//创建按钮2
QPushButton *pushBUtton2=new QPushButton("pushBUtton2");
pushBUtton2->setGeometry(10,100,100,30);
pushBUtton2->setParent(this);
// delete(pushBUtton1);
// delete(pushBUtton2);
}
MainWindow::~MainWindow()
{
delete ui;
}
主要代码和运行效果如下:
补充:
QPushButton 需要加上对应头文件,Qt一个类对应一个头文件(没有.h结尾),类名就是头文件名.
QDockWidget
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include<QDockWidget>
#include<QPalette>
#include<QLabel>
#include<QComboBox>
#include<QPushButton>
#include<QGridLayout>
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::MainWindow)
{
ui->setupUi(this);
QDockWidget *pDockwidget=new QDockWidget("Dock Widget",this);
pDockwidget->setMaximumSize(400,300);
pDockwidget->setAutoFillBackground(true);
//使用调色板设置颜色
QPalette pal;
pal.setColor(QPalette::Background,Qt::cyan);
pDockwidget->setPalette(pal);
QLabel *pLabel=new QLabel("学历:",this);
QComboBox *pCombx=new QComboBox(this);
pCombx->addItem("小学:");
pCombx->addItem("初中:");
pCombx->addItem("高中:");
QPushButton *pPushbt1=new QPushButton("985");
QPushButton *pPushbt2=new QPushButton("211");
//布局管理
QGridLayout *pGridlayout=new QGridLayout;
pGridlayout->addWidget(pLabel,0,0);
pGridlayout->addWidget(pCombx,0,1);
pGridlayout->addWidget(pPushbt1);
pGridlayout->addWidget(pPushbt2);
pGridlayout->setHorizontalSpacing(10);
pGridlayout->setVerticalSpacing(10);
pGridlayout->setContentsMargins(30,30,30,30);
//创建部件将其放入到铆接部件中,
QWidget *pWidget=new QWidget ;
pWidget->setLayout(pGridlayout); //设置布局
pDockwidget->setWidget(pWidget);
}
MainWindow::~MainWindow()
{
delete ui;
}
QFrame
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include<QDockWidget>
#include<QPalette>
#include<QLabel>
#include<QComboBox>
#include<QPushButton>
#include<QGridLayout>
#include<QVBoxLayout>
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::MainWindow)
{
ui->setupUi(this);
//创建中心部件
QWidget *pwidget_center=new QWidget;
this->setCentralWidget(pwidget_center);
//创建2个框架
QFrame *qFrame1=new QFrame;
qFrame1->setStyleSheet("background-color:yellow");
qFrame1->setLineWidth(4);
qFrame1->setMidLineWidth(1);
qFrame1->setFrameShape(QFrame::Box);
qFrame1->setFrameShadow(QFrame::Raised);//用于设置框架的“凸起”阴影效果
QFrame *qFrame2=new QFrame;
qFrame2->setStyleSheet("background-color:cyan");
qFrame2->setLineWidth(1);
qFrame2->setMidLineWidth(4);
qFrame2->setFrameShape(QFrame::Box);
qFrame2->setFrameShadow(QFrame::Sunken); //3D凹陷效果
QPushButton *pPushbt=new QPushButton(qFrame1);
pPushbt->setGeometry(20,20,40,20);
QVBoxLayout *pVboxlt=new QVBoxLayout;
pVboxlt->addWidget(qFrame1);
pVboxlt->addWidget(qFrame2);
//将部件添加到中心部件中
pwidget_center->setLayout(pVboxlt);
}
MainWindow::~MainWindow()
{
delete ui;
}
QGropBox
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::MainWindow)
{
ui->setupUi(this);
//组合框1:
QGroupBox *pGroupbox1=new QGroupBox("Grop1");
QRadioButton *pRadioBt1=new QRadioButton("Bt1");
QRadioButton *pRadioBt2=new QRadioButton("Bt2");
QRadioButton *pRadioBt3=new QRadioButton("Bt3");
QVBoxLayout *pVBoxlayout=new QVBoxLayout;
pVBoxlayout->addWidget(pRadioBt1);
pVBoxlayout->addWidget(pRadioBt2);
pVBoxlayout->addWidget(pRadioBt3);
pGroupbox1->setLayout(pVBoxlayout);
//组合框2
QGroupBox *pGroupbox2=new QGroupBox("Grop2");
QCheckBox *qCheckBox1=new QCheckBox("CheckBox1");
QCheckBox *qCheckBox2=new QCheckBox("CheckBox2");
QCheckBox *qCheckBox3=new QCheckBox("CheckBox3");
QVBoxLayout *pVBoxlayout2=new QVBoxLayout;
pVBoxlayout2->addWidget(qCheckBox1);
pVBoxlayout2->addWidget(qCheckBox2);
pVBoxlayout2->addWidget(qCheckBox3);
pGroupbox2->setLayout(pVBoxlayout2);
QHBoxLayout *qHBoxLayout=new QHBoxLayout;
qHBoxLayout->addWidget(pGroupbox1);
qHBoxLayout->addWidget(pGroupbox2);
//创建中心部件
QWidget *qWidget=new QWidget(this);
qWidget->setLayout(qHBoxLayout);
this->setCentralWidget(qWidget);
}
QCommandLinkButton
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::MainWindow)
{
ui->setupUi(this);
this->setGeometry(20,20,500,400);
this->setStyleSheet("QMainWindow {background-color:rgba(80,80,120,88%);}");
QCommandLinkButton *qCommandBt=new QCommandLinkButton("test","clicked",this);
qCommandBt->setGeometry(50,100,250,60);
connect(qCommandBt,&QCommandLinkButton::clicked,this,[](){
QDesktopServices::openUrl(QUrl("https://www.baidu.com/"));
});
}
QDialogButtonBox 按钮盒
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::MainWindow)
{
ui->setupUi(this);
QDialogButtonBox *pDialogBtBox=new QDialogButtonBox(this );
pDialogBtBox->setGeometry(100,100,200,200);
pDialogBtBox->addButton(QDialogButtonBox::Cancel);
pDialogBtBox->button(QDialogButtonBox::Cancel)->setText("cancle");
QPushButton *pPushBt=new QPushButton("PushBt");
pDialogBtBox->addButton(pPushBt,QDialogButtonBox::ActionRole);
}
QScrollArea 滚动区域
#include<QScrollArea>
#include<QGridLayout>
#include<QPicture>
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::MainWindow)
{
ui->setupUi(this);
//创建LAbel
QLabel *pLabel=new QLabel();
// pLabel->setScaledContents(true); // 设置标签内容缩放以适应标签大小
QImage Timage("C:\\Users\\86173\\Desktop\\3.png");
pLabel->setPixmap(QPixmap::fromImage(Timage));
QScrollArea* pScrollAre=new QScrollArea;
pScrollAre->setAlignment(Qt::AlignCenter); //剧中
pScrollAre->setWidgetResizable(true);//设置部件可调整尺寸
pScrollAre->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOn);// 设置水平滚动条始终显示
pScrollAre->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
pScrollAre->setWidget(pLabel);
//添加布局
QGridLayout *pGridlayout=new QGridLayout;
pGridlayout->addWidget(pScrollAre);
QWidget *qWidgetCenter=new QWidget;
qWidgetCenter->setLayout(pGridlayout);
this->setCentralWidget(qWidgetCenter);
}
QTreeWidget 树控件
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::MainWindow)
{
ui->setupUi(this);
QTreeWidget *treeWidget =new QTreeWidget(this);
treeWidget->setGeometry(100,100,200,200);
// 1:添加第一级节点
QTreeWidgetItem *topItem1=new QTreeWidgetItem( treeWidget);
topItem1->setText(0,"清华大学.");
topItem1->setCheckState(0,Qt::Checked);
treeWidget->addTopLevelItem(topItem1);
// 隐藏表头
treeWidget->setHeaderHidden(true);
// 展开节点
treeWidget->expandAll();
// 2:二级节点添加到一级节点的topItem1
QTreeWidgetItem *item11=new QTreeWidgetItem(topItem1);
item11->setText(0,"清华大学建筑学院.");
item11->setCheckState(0,Qt::Checked);
QTreeWidgetItem *item12=new QTreeWidgetItem(topItem1);
item12->setText(0,"清华大学建筑学院.");
item12->setCheckState(0,Qt::Checked);
QTreeWidgetItem *item13=new QTreeWidgetItem(topItem1);
item13->setText(0,"清华大学土木学院.");
item13->setCheckState(0,Qt::Checked);
QTreeWidgetItem *item14=new QTreeWidgetItem(topItem1);
item14->setText(0,"清华大学信息科学技术学院.");
item14->setCheckState(0,Qt::Checked);
QTreeWidgetItem *item15=new QTreeWidgetItem(topItem1);
item15->setText(0,"清华大学马克思主义学院.");
item15->setCheckState(0,Qt::Checked);
// 3:添加第一级节点
QTreeWidgetItem *topItem2=new QTreeWidgetItem( treeWidget);
topItem2->setText(0,"北京大学.");
topItem2->setCheckState(0,Qt::Checked);
treeWidget->addTopLevelItem(topItem2);
QTreeWidgetItem *item21=new QTreeWidgetItem(topItem2);
item21->setText(0,"北京大学数学科学学院.");
item21->setCheckState(0,Qt::Checked);
QTreeWidgetItem *item22=new QTreeWidgetItem(topItem2);
item22->setText(0,"北京大学软件与微电子学院.");
item22->setCheckState(0,Qt::Checked);
QTreeWidgetItem *item23=new QTreeWidgetItem(topItem2);
item23->setText(0,"北京大学新闻与传播学院.");
item23->setCheckState(0,Qt::Checked);
QTreeWidgetItem *item24=new QTreeWidgetItem(topItem2);
item24->setText(0,"北京大学光华管理学院.");
item24->setCheckState(0,Qt::Checked);
QTreeWidgetItem *item25=new QTreeWidgetItem(topItem2);
item25->setText(0,"北京大学医学部.");
item25->setCheckState(0,Qt::Checked);
}
QTreeView 树视图
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::MainWindow)
{
ui->setupUi(this);
// 1:构造model
QStandardItemModel *sItemMode = new QStandardItemModel ;
//设置列头
sItemMode->setHorizontalHeaderLabels(QStringList()<<QStringLiteral("编号.") << QStringLiteral("初中部|高中部."));
// 创建一级节点,将它加入到sItemModel
QList<QStandardItem*> item11;
QStandardItem *item1=new QStandardItem(QString::number(1));
QStandardItem *item2=new QStandardItem("初中部.");
item11.append(item1);
item11.append(item2);
sItemMode->appendRow(item11);
// 二级节点,添加到第一个一级节点
QList<QStandardItem*> item112;
QStandardItem *item1121=new QStandardItem(QString::number(2));
QStandardItem *item1122=new QStandardItem(QStringLiteral("一年级."));
item112.append(item1121);
item112.append(item1122);
item1->appendRow(item112);
// 三级节点,添加到第一个二级节点
QList<QStandardItem*> item1231;
QStandardItem *item12311=new QStandardItem(QString::number(3));
QStandardItem *item12312=new QStandardItem(QStringLiteral("一班."));
item1231.append(item12311);
item1231.append(item12312);
item1121->appendRow(item1231);
QList<QStandardItem*> item1232;
QStandardItem *item12321=new QStandardItem(QString::number(3));
QStandardItem *item12322=new QStandardItem(QStringLiteral("二班."));
item1232.append(item12321);
item1232.append(item12322);
item1121->appendRow(item1232);
QList<QStandardItem*> item1233;
QStandardItem *item12331=new QStandardItem(QString::number(3));
QStandardItem *item12332=new QStandardItem(QStringLiteral("三班."));
item1233.append(item12331);
item1233.append(item12332);
item1121->appendRow(item1233);
// 创建一级节点,将它加入到sItemModel
QList<QStandardItem*> item12;
QStandardItem *item3=new QStandardItem(QString::number(2));
QStandardItem *item4=new QStandardItem("高中部.");
item12.append(item3);
item12.append(item4);
sItemMode->appendRow(item12);
// 2:给QTreeView应用model
QTreeView* pTreeView=new QTreeView(this) ;
pTreeView->setGeometry(120,120,400,300);
pTreeView->setModel(sItemMode);
}
QStackedWidget 堆栈部件
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::MainWindow)
{
ui->setupUi(this);
QListWidget* qlist=new QListWidget(this);
qlist->setGeometry(160,160,260,200);
qlist->insertItem(0,"Linux1");
qlist->insertItem(1,"Linux2");
qlist->insertItem(2,"Linux3");
qlist->insertItem(3,"Linux4");
qlist->insertItem(4,"Linux5");
QLabel* lab1=new QLabel("Linux1 Qt");
QLabel* lab2=new QLabel("Linux2 Qt");
QLabel* lab3=new QLabel("Linux3 Qt");
QLabel* lab4=new QLabel("Linux4 Qt");
QLabel* lab5=new QLabel("Linux5 Qt");
static QStackedWidget* statcks=new QStackedWidget(this);
statcks->setGeometry(30,30,120,100);
statcks->addWidget(lab1);
statcks->addWidget(lab2);
statcks->addWidget(lab3);
statcks->addWidget(lab4);
statcks->addWidget(lab5);
statcks->insertWidget(5,lab5);
statcks->setCurrentIndex(0); // 显示窗口
static int num=0;
//添加布局器
QHBoxLayout *mlayout=new QHBoxLayout ;
QPushButton *ptn=new QPushButton(this);
connect(ptn,&QPushButton::clicked,[&]()mutable{
num=num%5;
statcks->setCurrentIndex(num++);
});
mlayout->setMargin(10);
mlayout->setSpacing(20);
mlayout->addWidget(qlist);
mlayout->addWidget(statcks,0,Qt::AlignCenter);
mlayout->addWidget(ptn);
//设置比例因子
mlayout->setStretchFactor(qlist,1);
mlayout->setStretchFactor(statcks,5);
QWidget *pWidget=new QWidget;
pWidget->setLayout(mlayout);
this->setCentralWidget(pWidget);
}
2、信号和槽机制
a、使用系统自带的信号和槽,核心代码如下:
#include<QPushButton>
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::MainWindow)
{
ui->setupUi(this);
this->setFixedSize(400,300); //设置主窗口尺寸
this->setWindowTitle("Hell Qt");
//创建按钮1
QPushButton *pushBUtton1=new QPushButton("pushBUtton1",this);
pushBUtton1->setGeometry(10,10,100,30); //设置位置和大小
//第一种
//connect(pushBUtton1,&QPushButton::clicked,this,&MainWindow::close);
//第二种
connect(pushBUtton1,SIGNAL(clicked(bool)),this,SLOT(close()));
}
b.使用自定义信号和槽传递参数
自定义类:
class CTeacher:public QObject
{
Q_OBJECT
public:
CTeacher(QObject* object=nullptr):QObject(object)
{
void (CTeacher::*pSingProc)(QString str)=&CTeacher::sing_eat;
void (CTeacher::*pSlotProc)(QString str)=&CTeacher::onslo_eat;
connect(this,pSingProc,this,pSlotProc);
// connect(this,SIGNAL(sing_eat(QString)),this,SLOT(onslo_eat(QString)));
}
public slots:
void onslo_eat(QString str) //自定义槽函数
{
qDebug()<<str;
}
signals:
void sing_eat(QString str); //信号
};
创建对象并且使用:
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::MainWindow)
{
ui->setupUi(this);
this->setFixedSize(300,200);
CTeacher *Ct=new CTeacher;
emit Ct->sing_eat("Hello World!"); // 直接触发信号
}
运行效果
3.lambda表达式
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::MainWindow)
{
ui->setupUi(this);
this->setFixedSize(300,200);
static QPushButton *pushbutton=new QPushButton(this);
pushbutton->setGeometry(80,80,60,30);
//lambda 的使用1
[](){
qDebug()<<"lambda!";
}();
//lambda 的使用2
static int number=10;
auto MyLambdaFunc=[&](int num=-1)mutable {
number=number+num-1;
pushbutton->setText(QString::number(number));
};
connect(pushbutton,&QPushButton::clicked,MyLambdaFunc);
}
运行结果
信号槽是 Qt 框架引以为豪的机制之一。所谓信号槽,实际就是观察者模式。当某个事件发生之后,比如,按钮检测到自己被点击了一下,它就会发出一个信号(signal)。这种发出是没有目的的,类似广播。如果有对象对这个信号感兴趣,它就会使用连接(connect)函数,意思是,将想要处理的信号和自己的一个函数(称为槽(slot))绑定来处理这个信号。也就是说,当信号发出时,被连接的槽函数会自动被回调。这就类似观察者模式:当发生了感兴趣的事件,某一个操作就会被自动触发。
注意:
- 发送者和接收者都需要是QObject的子类(当然,槽函数是全局函数、Lambda 表达式等无需接收者的时候除外);
- 信号和槽函数返回值是 void
- 信号只需要声明,不需要实现
- 槽函数需要声明也需要实现
- 槽函数是普通的成员函数,作为成员函数,会受到 public、private、protected 的影响;
- 使用 emit 在恰当的位置发送信号;
- 使用connect()函数连接信号和槽。
- 任何成员函数、static 函数、全局函数和 Lambda 表达式都可以作为槽函数
- 信号槽要求信号和槽的参数一致,所谓一致,是参数类型一致。
- 如果信号和槽的参数不一致,允许的情况是,槽函数的参数可以比信号的少,即便如此,槽函数存在的那些参数的顺序也必须和信号的前面几个一致起来。这是因为,你可以在槽函数中选择忽略信号传来的数据(也就是槽函数的参数比信号的少)。
4、QMainWindow
QMainWindow 是一个为用户提供主窗口程序的类,包含一个菜单栏(menu bar)、多个工具栏(tool bars)、多个锚接部件(dock widgets)、一个状态栏(status bar)及一个中心部件(central widget),是许多应用程序的基础,如文本编辑器,图片编辑器等。
创建菜单栏(一个)
//创建菜单栏
void MainWindow::OnCreateMenuBar()
{
//创建菜单栏
m_menuBar =new QMenuBar;
//m_menuBar=this->menuBar();
this->setMenuBar(m_menuBar);
//创建菜单1
QMenu *menu1=new QMenu ;
menu1->setTitle("menu1"); //设置子菜单名字
menu1->addAction("open");
menu1->addAction("exit");
//添加菜单1到菜单栏中
m_menuBar->addMenu(menu1);
QMenu *menu2=m_menuBar->addMenu("menu2");
menu2->addAction("pasue");
menu2->addAction("stop");
//void QMenu::triggered(QAction *action)
connect(menu1,&QMenu::triggered,this,&MainWindow::slot_clickMenu);
}
创建工具栏(多个)
void MainWindow::OnCreateToolBar()
{
//创建工具栏
m_toolBar=new QToolBar ;
this->addToolBar(Qt::BottomToolBarArea,m_toolBar);
//使用setAllowedAreas()函数指定停靠区域:
m_toolBar->setAllowedAreas(Qt::LeftToolBarArea|Qt::BottomToolBarArea);
//m_toolBar->setMovable(false); //禁止停靠
//增加按钮动作
QAction *action_=new QAction(QIcon("C:\\Users\\86173\\Desktop\\3.png"),"help");
m_toolBar->addAction(action_);
m_toolBar->addAction("Tool_edit");
// void actionTriggered(QAction *action);
connect(m_toolBar,&QToolBar::actionTriggered,this,&MainWindow::Slot_StopMove);
}
创建状态栏
void MainWindow::OnCreatStatuBar()
{
// QStatusBar *m_statubar=new QStatusBar;
// this->setStatusBar(m_statubar);
// 创建一个QLabel作为状态栏的小部件
QLabel *permanentWidget1 = new QLabel("tile1");
QLabel *permanentWidget2 = new QLabel("tile2");
// 获取状态栏指针
QStatusBar *statusBar = this->statusBar();
statusBar->addWidget(permanentWidget1);
statusBar->addPermanentWidget(permanentWidget2);
// 显示一条简单消息,注意这可能会覆盖或隐藏之前添加的小部件
statusBar->showMessage("Ready", 2000); // 2000毫秒后自动消失
}
创建铆接部件(可以有多个)
QDockWidget * dock = new QDockWidget("MyDocWidget",this);
this->addDockWidget(Qt::LeftDockWidgetArea,dock);
//设置停靠
dock->setAllowedAreas(Qt::LeftDockWidgetArea|Qt::RightDockWidgetArea);
创建中心部件
QLineEdit *p_lineedit_=new QLineEdit;
this->setCentralWidget(p_lineedit_);
总体效果图
5、QString
// 构造QString
QString str1{"Hello world!"};
QString str2=str1;
qDebug()<<str1;
// append 追加
QString str3="China";
str3.append(str2);
qDebug()<<qPrintable(str2);//去除""
//sprintf 格式化参数
str1="";
str1.sprintf("%s:%s","Data","Year");
qDebug()<<qPrintable(str1)<<qPrintable(QString::number(2024));// QString::number(2024)
//arg 替换占位符
str2.clear();
str1=QString("%1 was born in %2").arg("sunny").arg(2000);
// startwith 用于检查字符串是否以指定的前缀开始
str2="hello world!";
qDebug()<<str2.startsWith("Hello"); //默认考虑大小写。
qDebug()<<str2.startsWith("hello",Qt::CaseInsensitive); //不区分大小写
qDebug()<<str2.startsWith("Hello",Qt::CaseInsensitive);
//QString::contains 检查字符串中是否包含某个特定的子字符串或字符。
str3="hello word!";
qDebug()<<str3.contains("wor",Qt::CaseInsensitive);
//toint qstring->int
QString strnumber{"1997"};
bool bvalue;
int inumber=strnumber.toInt(&bvalue);
qDebug()<<inumber;
//QString -> ascll
QString strTemp="ABC abc";
QByteArray arrByte=strTemp.toUtf8();
for(auto i:arrByte)
qDebug()<<i;
//QDateTime 类
QDateTime CTime=QDateTime::currentDateTime();
qDebug()<<CTime;
QString strDT=CTime.toString("yyyy-mm-dd hh:mm:ss");
qDebug()<<strDT;
三、进阶
1、无边框拖拽移动窗口
#ifndef FRAMELESSWIDGET_H
#define FRAMELESSWIDGET_H
#include <QWidget>
#include <windows.h> //注意头文件
#include <windowsx.h>
#include <QMouseEvent>
class FramelessWidget : public QWidget
{
Q_OBJECT
public:
FramelessWidget(QWidget *parent = 0);
~FramelessWidget();
protected:
bool nativeEvent(const QByteArray &eventType, void *message, long *result);
void mousePressEvent(QMouseEvent *e);
void mouseMoveEvent(QMouseEvent *e);
private:
int boundaryWidth;
QPoint clickPos;
};
#endif // FRAMELESSWIDGET_H
#include "widget.h"
FramelessWidget::FramelessWidget(QWidget *parent)
: QWidget(parent)
{
boundaryWidth=4; //设置触发resize的宽度
this->setWindowFlags(Qt::FramelessWindowHint); //设置为无边框窗口
this->setMinimumSize(45,45); //设置最小尺寸
this->setStyleSheet("background:#D1EEEE"); //设置背景颜色
}
FramelessWidget::~FramelessWidget()
{
}
bool FramelessWidget::nativeEvent(const QByteArray &eventType, void *message, long *result)
{
MSG* msg = (MSG*)message;
switch(msg->message)
{
case WM_NCHITTEST:
int xPos = GET_X_LPARAM(msg->lParam) - this->frameGeometry().x();
int yPos = GET_Y_LPARAM(msg->lParam) - this->frameGeometry().y();
if(xPos < boundaryWidth && yPos<boundaryWidth) //左上角
*result = HTTOPLEFT;
else if(xPos>=width()-boundaryWidth&&yPos<boundaryWidth) //右上角
*result = HTTOPRIGHT;
else if(xPos<boundaryWidth&&yPos>=height()-boundaryWidth) //左下角
*result = HTBOTTOMLEFT;
else if(xPos>=width()-boundaryWidth&&yPos>=height()-boundaryWidth)//右下角
*result = HTBOTTOMRIGHT;
else if(xPos < boundaryWidth) //左边
*result = HTLEFT;
else if(xPos>=width()-boundaryWidth) //右边
*result = HTRIGHT;
else if(yPos<boundaryWidth) //上边
*result = HTTOP;
else if(yPos>=height()-boundaryWidth) //下边
*result = HTBOTTOM;
else //其他部分不做处理,返回false,留给其他事件处理器处理
return false;
return true;
}
return false; //此处返回false,留给其他事件处理器处理
}
void FramelessWidget::mousePressEvent(QMouseEvent *e)
{
if(e->button()==Qt::LeftButton)
clickPos=e->pos();
}
void FramelessWidget::mouseMoveEvent(QMouseEvent *e)
{
if(e->buttons()&Qt::LeftButton)
move(e->pos()+pos()-clickPos);
}
2、序列化结构体
#include <QDataStream>
#include <QFile>
#include <QDebug>
struct MyStruct {
int id;
QString name;
float value;
// 为了方便,我们可以添加一个构造函数来初始化结构体
MyStruct(int id = 0, const QString &name = QString(), float value = 0.0f)
: id(id), name(name), value(value) {}
};
// 写入结构体到QDataStream
QDataStream &operator<<(QDataStream &out, const MyStruct &structData) {
out << structData.id << structData.name << structData.value;
return out;
}
// 从QDataStream读取结构体
QDataStream &operator>>(QDataStream &in, MyStruct &structData) {
in >> structData.id >> structData.name >> structData.value;
return in;
}
// 写入结构体到文件
void writeStructToFile(const MyStruct &data, const QString &filePath) {
QFile file(filePath);
if (!file.open(QIODevice::WriteOnly)) {
qWarning("Could not open file for writing.");
return;
}
QDataStream out(&file);
out << data;
file.close();
}
// 从文件读取结构体
MyStruct readStructFromFile(const QString &filePath) {
QFile file(filePath);
if (!file.open(QIODevice::ReadOnly)) {
qWarning("Could not open file for reading.");
return MyStruct();
}
QDataStream in(&file);
MyStruct data;
in >> data;
file.close();
return data;
}
// 使用示例
int main() {
MyStruct originalData = {1, "Example", 3.14f};
QString filePath = "C:/Users/86173/Desktop/test/qt/qianfen/untitled62/struct_data.dat";
// 写入结构体到文件
writeStructToFile(originalData, filePath);
// 从文件读取结构体
MyStruct readData = readStructFromFile(filePath);
// 输出读取的结构体数据
qDebug() << "Read struct:" << readData.id << readData.name << readData.value;
return 0;
}