声明:本文档部分内容参考自网络(用作笔记),如有侵权可联系笔者删除。
下载链接: https://download.qt.io/archive/qt/5.9/5.9.0/qt-opensource-windows-x86-5.9.0.exe.
注释 Ctrl + /
运行 ctrl + r
编译 ctrl + b
查找 ctrl + f
整行移动 ctrl + shift + ↑/↓
帮助文档 F1 退出 esc;第二种帮助文档:assitent.exe : \Qt\Qt5.9.0\5.9\mingw53_32\bin
自动对齐 ctrl + i
同名之间的.h和.cpp之间的切换 F4
基本思路: 利用Qt安装目录(笔者的安装目录是:D:\Qt\Qt5.9.0\5.9\mingw53_32\bin)下的windeployqt.exe工具来生成,具体步骤如下:
例: 打包hello.exe(release方式编译)
“:+前缀名+文件名”
#-------------------------------------------------
#
# Project created by QtCreator 2022-03-24T15:47:40
#
#-------------------------------------------------
QT += core gui ##QT包含的模块,core gui
greaterThan(QT_MAJOR_VERSION, 4): QT += widgets ## 大于4版本 包含widgets模块
TARGET = bin2hex ## 生成的目标的文件名
TEMPLATE = app ## 模板 应用程序模板(app),即指定编译成可执行文件(.exe);
## 库模板(lib)
## vcapp 建立一个应用程序的VisualStudio项目文件
## vclib 建立一个库的VisualStudio项目文件
## subdir 这是一个特殊的模板,可以进入特定子目录并为该项目文件生成makefile。
# The following define makes your compiler emit warnings if you use
# any feature of Qt which as been marked as deprecated (the exact warnings
# depend on your compiler). Please consult the documentation of the
# deprecated API in order to know how to port your code away from it.
DEFINES += QT_DEPRECATED_WARNINGS
# You can also make your code fail to compile if you use deprecated APIs.
# In order to do so, uncomment the following line.
# You can also select to disable deprecated APIs only up to a certain version of Qt.
#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0
## 源文件
SOURCES += \
main.cpp \
mywidget.cpp
## 头文件
HEADERS += \
mywidget.h
#include "mywidget.h"
#include // 包含一个应用程序类的头文件
int main(int argc, char *argv[])
{
QApplication a(argc, argv); //应用程序对象,在QT中应用程序有且只有一个。
myWidget w; //窗口对象。该myWidget的父类是QWideget
w.show(); //串口对象默认不会显示,必须调用show方法来显示。
return a.exec(); //让应用程序对象,进入消息循环机制。让代码阻塞等待窗口的消息。
/**
*该消息循环机制可以简单认为是下面的伪代码:
*while(true) {
* if(点击叉子)
* break;
*}
**/
}
#include "mywidget.h"
myWidget::myWidget(QWidget *parent)
: QWidget(parent) //初始化列表
{
}
myWidget::~myWidget()
{
}
#ifndef MYWIDGET_H
#define MYWIDGET_H
#include
class myWidget : public QWidget
{
Q_OBJECT //允许类中使用信号和槽机制
public:
myWidget(QWidget *parent = 0); //构造函数,默认参数
~myWidget(); //析构函数
};
#endif // MYWIDGET_H
qt使用对象树,简化了资源释放的操作(QObject派生的类)。
通过setParent函数将Qt中的对象添加到对象树中。
析构的顺序: 在析构当前对象时,执行当前对象的析构函数,在当前对象的析构函数中,会寻找当前对象的子对象;即,先析构所有子对象,再析构当前对象。自下而上的顺序。
–>x
|
|/
y
左上角为原点,水平方向往右为x轴正半轴;垂直方向往下为y轴正半轴。
QWidget: 最简单的窗口什么都没有。
QMainWindow:带有简单菜单栏、状态栏等的窗口
QDialog:对话框(一般不带,最小化和最大化的按钮,一般带有选择性的按钮,如“确认”,“去取消”等)
上述3个基类之间的关系:
QMainWindow继承自QWidget。
QDialog继承自QWidget。
即:
QWidget是QMainWindow和QDialog的父类。
resize(宽,高);
setFixedsize(宽,高);
setWindowTitile("文本");
static const QDateTime buildDateTime()
{
QString dateTime;
dateTime += __DATE__;
dateTime += __TIME__;
qDebug() << dateTime;
return QLocale(QLocale::English).toDateTime(dateTime.replace(" ", " 0"), "MMM dd yyyyhh:mm:ss");
}
QString getWinTitle(QString title, QString version)
{
title += " ";
title += version;
title += " (";
title += buildDateTime().toString("yyyy-MM-dd HH:mm:ss");
title += ")";
return title;
}
setWindowTitle(getWinTitle("标题","版本: V1.00"));
在QMainWindow中菜单栏有且仅有一个。
QMenuBar *mbar = MenuBar()
setMenuBar(mbar)
QMenu *fileMenu = addMenu("文件")
QAction *newAction = mbar->addAction("新建")
mbar->addseparator()
在QMainWindow中工具栏可以有多个
QToolBar *toolBar = new QToolBar(this);
addToolBar(默认停靠的区域,toolBar)
默认停靠的区域:Qt::LeftToolBarArea
var_ToolBar->setAllowedAreas(Qt::LeftToolBarArea | Qt::RightToolBarArea);
var_ToolBar->setFloatabloo(false);
var_ToolBar->setMovable(false);
var_ToolBar->addAction(newAction);
var_ToolBar->addSeparator();
QPushButton *btn = new QPushButton("按钮",this);
var_ToolBar->addWidget(btn);
最多只有一个
QStatusBar *sbar = statusBar()
setStatusBar(sbar)
sbar->addWidget(label);
sbar->addPermanentWidget(label2);
QDockWidget *dwt = QDockWidget("浮动窗口",this)
addDockWidget(Qt::RightDockWidgetArea,dwt);
dwt->setAllowedAreas(Qt::RightDockWidgetArea | Qt::TopDockWidgetArea);
QTextEdit *edit = new QTextEdit(this);
setCentralWidget(edit);
对话框有两种分类:模态对话框,非模态对话框
不可以操作其它窗口
创建
QDiaglog dlg(this);
dlg.resize(200,100);
dlg.exec();
可以操作其它窗口
QDiaglog *dlg2 = QDiaglog(this);
dlg2->resize(200,100);
dlg2->setAttribute(Qt::WA_DeletOnClose);//防止重复创建对象
dlg2->show();
QMessageBox有四个标准对话框,可以使用静态成员函数来创建。
表准对话框的静态成员函数的参数及返回值的意义:
参数1,父亲
参数2, 标题
参数3,提问信息
参数4,默认标准按钮
参数5,默认关联回车的按键
返回值:点击的按钮。可以用来判断点击了的按钮。
QMessageBox::critical(this,"title","message");
QMessageBox::information(this,"title","message");
QMessageBox::question(this,"title","在?",QMessageBox::Save | QMessageBox::Cancel,QMessageBox::Cancel);
if(QMessageBox::Save == QMessageBox::question(this,"title","在?",QMessageBox::Save | QMessageBox::Cancel))
{
qDebug() << "保存";
}
else {
qDebug() << "取消";
}
QMessageBox::warning(this,"title","你好!");
QColor color = QColorDialog::getColor(QColor(0,255,0));
qDebug() << "r = " << color.red() << "g = " << color.green() << "b = " << color.blue();
QString str = QFileDialog::getOpenFileName(this,"title","C:","(*.txt)");
qDebug() << str;
参数1: 父亲
参数2:标题
参数3:默认打开的文件夹路径
参数4:指定显示的文件后缀
返回值:打开的文件的路径。
bool flag;
QFont font = QFontDialog::getFont(&flag,QFont("宋体",36),this,"选择字体");
qDebug() << "字体" << font.family() << "字号" << font.pointSize()<< "加粗?" << font.bold() << "倾斜?" << font.italic();
参数1: bool返回值
参数2:默认字头 QFont(字体,大小);
参数3:父亲
参数4:标题
返回值:QFont 从中可以获取到,选择的字体、字号、加粗、倾斜等信息。
QpushButton *btn = new QpushButton;
btn->setparent(this);
btn->setText("按钮1");
btn->move(宽,高);
可以使用父类QWidget中设置大小的函数。
阿拉丁神灯:
人 摩擦 --> 灯 出灯神
【信号的发送者】 【要发送的信号】 【信号的接收者】 【信号的处理(槽函数)】
在Qt中,使用connect函数来实现:
connect(信号的发送者, 发送的信号, 信号的接收者, 处理的槽函数);
信号与槽的优点:松散耦合,将本没有关联的 “信号的发送者”、“信号”、“信号的接收者”、“处理槽函数”之间关联起来。
例如:
connect(ptrCloseButton, &QPushButton::clicked, this, &QWidget::close);
可以查看对象的类,寻找信号,寻找处理槽函数。
connect(ptrCloseButton, &QPushButton::clicked, this, &QWidget::close);
参数1:信号的发送者
参数2:信号
参数3:信号的接收者
参数3:处理的槽函数
下课后,老师饿了,学生
#ifndef TEACHER_H
#define TEACHER_H
#include
class Teacher : public QObject
{
Q_OBJECT
public:
explicit Teacher(QObject *parent = nullptr);
signals:
void hungry();
void hungry(QString string);
public slots:
};
#endif // TEACHER_H
#ifndef STUDENT_H
#define STUDENT_H
#include
class student : public QObject
{
Q_OBJECT
public:
explicit student(QObject *parent = nullptr);
signals:
public slots:
void treat();
void treat(QString string);
};
#endif // STUDENT_H
#include "student.h"
#include
student::student(QObject *parent) : QObject(parent)
{
}
void student::treat()
{
qDebug() << "请客吃饭";
}
在触发函数中使用emit 触发信号。
void myWidget::classIsOver()
{
emit tch->hungry();
}
main()
{
//...
connect(tch, &Teacher::hungry, stu, &student::treat);
classIsOver();
//...
}
disconnect(信号的发送者,信号, 信号的接收者, 处理的槽函数);
断开信号与槽。
connect(zt, SIGNAL(hungry(), st, SLOT(treat()));
[capture](parametres)mutable->return-type
{
statement
}
/*
[函数对象参数](操作符重载函数参数)mutable->返回值
{
函数体
}
*/
[]
标志着lambda表达式的开始,不能省略!
[]
中可以传入参数=
: 函数体可以使用lambda所在作用域范围内可见的局部变量(包括this),值传递方式。&
: 函数体可以使用lambda所在作用域范围内可见的局部变量(包括this),引用传递方式。()
标志着操作符重载的函数参数,当不存在参数时,可以省略。参数可按值传递,也可以引用传递。
mutable声明,可以省略。加上mutable修饰符之后,可以修改按值传递进来的拷贝(注意是拷贝,而不是本身)。
[capture](parametres)mutable->return-type
{
statement
}();
//使用lambda表达式作为槽函数时,信号的接收者可以省略.
connect(信号的发送者, 信号,[=](){
this->close();
});
使用lambda表达式作为槽函数时,信号的接收者可以省略
常用按钮,一般用于显示文字
常用按钮,默认显示图片(Icon)可以修改属性:toolButtonStyle为ToolButtonBesideIcon。凸起风格:autoRaise
单选按钮,可以使用GroupBox来将单选按钮进行分组。
使用setChecked(true)默认选中
多选按钮,可以使用GroupBox来将多选按钮进行分组。
监听状态,stateChanged(int state),
state 0: 未选中
state 1: 半选(表示旗下有多个子多选按钮,当旗下没有全选时,显示该状态。)
state 2: 选中
清除内容
ui->comboBox->clear();
ui->comboBox->addItem(QString(name));
ui->comboBox->setCurrentIndex(2);
void (QComboBox::*signalCurrentIndexChanged)(int) = &QComboBox::currentIndexChanged;
connect(ui->comboBox,signalCurrentIndexChanged,[=](int index){
qDebug() << "comboBoxModelSelect Changed:" << index;
if(index >= 0) {
// handle
}
});
暂停信号触发
ui->comboBox->blockSignals(true);
恢复信号触发
ui->comboBox->blockSignals(false);
基于模型的控件,例如数据库模型
其中包含:List View、Tree View、 Table View、 Column View等。
基于内容的 Widget
对于ListWidget而言,其中的每一行都是QListWidgetitem *item类型的对象。
QListWidgetitem *item = new QListWidgetitem("锄禾日当午");
ui->listWidget->additem(QListWidgetitem);
item->setTextAlignment(Qt::AlignmentCenter);
QStringList list;
list << "锄禾日当午" << "汗滴禾下土" << "谁之盘中餐" << "粒粒皆辛苦";
ui->listWidget->additems(QStringList);
ui->tableWidget->setSelectionBehavior(QAbstractItemView::SelectRows); // 整行选中的方式
ui->tableWidget->setSelectionMode(QAbstractItemView::ExtendedSelection); // 设置为可以选中多个目标
ui->tableWidget->verticalHeader()->setVisible(false); // 隐藏行表头
ui->tableWidget->resizeColumnsToContents(); // 列宽与内容匹配
ui->tableWidget->resizeRowsToContents(); // 行高与内容匹配
ui->tableWidget->resizeColumnToContents(0); // 自动调整列宽
ui->tableWidget->setColumnCount(5); // 设置列数
QHeaderView* widthlist = ui->tableWidget->horizontalHeader(); //创建列宽list
//widthlist->setStyleSheet("QHeaderView::section{border:0px;background-color:#f2f1f7;color:#7f7f7f;}");//设置颜色
widthlist->resizeSection(0, 40); // 设置列宽
widthlist->resizeSection(1, 120);
widthlist->resizeSection(2, 100);
widthlist->resizeSection(3, 100);
widthlist->setStretchLastSection(true); // 最后一栏自适应宽度
QStringList list; // 创建列表头list
list << "NO." << "PartName" << "offset" << "size" << "firmware";
ui->tableWidget->setHorizontalHeaderLabels(list);
ui->tableWidget->show();
int i = 0; /*i 代表行号 */
while(partSelect != NULL) {
//===============控件tableWidget操作新增数据===========================
int rowcount = ui->tableWidget->rowCount(); //获取当前行数
if (rowcount < i+1) //如果添加的数据所在的行数大于实际控件存在的列数,则新增一列
{
ui->tableWidget->insertRow(rowcount); //新增行
}
ui->tableWidget->setItem(i, 0, new QTableWidgetItem(QString::number(i))); //新增行添加数据
ui->tableWidget->item(i,0)->setTextAlignment(Qt::AlignCenter); //设置单元格对齐方式为中心对齐
ui->tableWidget->setItem(i, 1, new QTableWidgetItem(QString(partSelect->partName)));
ui->tableWidget->item(i,1)->setTextAlignment(Qt::AlignCenter);
ui->tableWidget->setItem(i, 2, new QTableWidgetItem(QString::number(partSelect->offsetAddr,16)));
ui->tableWidget->item(i,2)->setTextAlignment(Qt::AlignCenter);
ui->tableWidget->setItem(i, 3, new QTableWidgetItem(QString::number(partSelect->totalSize,16)));
ui->tableWidget->item(i,3)->setTextAlignment(Qt::AlignCenter);
ui->tableWidget->setItem(i, 4, new QTableWidgetItem(QString(partSelect->firmware)));
/*设置每行的0~3列的单元格不可更改(不可编辑)*/
for(int j = 0;j < 5;j ++) {
QTableWidgetItem* pItem = ui->tableWidget->item(i, j);
pItem->setFlags(pItem->flags() & (~Qt::ItemIsEditable));
}
partSelect = partSelect->next;
i ++;
}
QTableWidgetItem* pItem = ui->tableWidget->item(i, j);
pItem->setFlags(pItem->flags() & (~Qt::ItemIsEditable));
while (ui->tableWidget->rowCount()>0)
{
ui->tableWidget->removeRow(0);
}
QModelIndexList list = ui->tableWidget->selectionModel()->selectedRows();
int count = list.count(); //选中的行数
if(count > 0) {
for(int i =0 ; i<count ;i++){
int row = list.at(i).row();
if(row >= 0) {
//handle
}
}
}
默认从选中行之前插入,选中几行,则插入几行,并且自动更新行序号;无选中行,则从最后的行尾插入,并且自动更新行序号。
QModelIndexList list = ui->tableWidget->selectionModel()->selectedRows();
int count = list.count();
if(count > 0) {
int row = list.at(0).row();
int NO = row + count;
qDebug() << "add " << count << ((count == 1)?" line":" lines");
for(int i =0 ; i<count ;i++){
if(row >= 0) {
ui->tableWidget->insertRow(row);
NO --;
ui->tableWidget->setItem(row, 0, new QTableWidgetItem(QString::number(NO))); //新增行添加数据
ui->tableWidget->item(row,0)->setTextAlignment(Qt::AlignCenter);
ui->tableWidget->setItem(row, 1, new QTableWidgetItem(QString("")));
ui->tableWidget->item(row,1)->setTextAlignment(Qt::AlignCenter);
ui->tableWidget->setItem(row, 2, new QTableWidgetItem(QString("")));
ui->tableWidget->item(row,2)->setTextAlignment(Qt::AlignCenter);
ui->tableWidget->setItem(row, 3, new QTableWidgetItem(QString("")));
ui->tableWidget->item(row,3)->setTextAlignment(Qt::AlignCenter);
ui->tableWidget->setItem(row, 4, new QTableWidgetItem(QString("")));
}
}
for(int i = row + count;i < ui->tableWidget->rowCount();i ++) {
ui->tableWidget->setItem(i, 0, new QTableWidgetItem(QString::number(i))); //设置剩余行的 NO
ui->tableWidget->item(i,0)->setTextAlignment(Qt::AlignCenter);
}
}
else { //无选中行,则从最后的行尾插入
int rowcount = ui->tableWidget->rowCount();
ui->tableWidget->insertRow(rowcount);
ui->tableWidget->setItem(rowcount, 0, new QTableWidgetItem(QString::number(rowcount))); //从尾部插入
ui->tableWidget->item(rowcount,0)->setTextAlignment(Qt::AlignCenter);
ui->tableWidget->setItem(rowcount, 1, new QTableWidgetItem(QString("")));
ui->tableWidget->item(rowcount,1)->setTextAlignment(Qt::AlignCenter);
ui->tableWidget->setItem(rowcount, 2, new QTableWidgetItem(QString("")));
ui->tableWidget->item(rowcount,2)->setTextAlignment(Qt::AlignCenter);
ui->tableWidget->setItem(rowcount, 3, new QTableWidgetItem(QString("")));
ui->tableWidget->item(rowcount,3)->setTextAlignment(Qt::AlignCenter);
ui->tableWidget->setItem(rowcount, 4, new QTableWidgetItem(QString("")));
}
默认删除选中行,选中几行,则删除几行,并且自动更新行序号;无选中行,则删除最末行,并且自动更新行序号。
QModelIndexList list = ui->tableWidget->selectionModel()->selectedRows();
int count = list.count();
if(count > 0) {
int row = list.at(0).row();
qDebug() << "remove " << count << ((count == 1)?" line":" lines");
for(int i =0 ; i<count ;i++){
if(row >= 0) {
ui->tableWidget->removeRow(row);
}
}
for(int i = row;i < ui->tableWidget->rowCount();i ++) {
ui->tableWidget->setItem(i, 0, new QTableWidgetItem(QString::number(i))); //设置剩余行的 NO
ui->tableWidget->item(i,0)->setTextAlignment(Qt::AlignCenter);
}
}
else {
int rowcount = ui->tableWidget->rowCount();
ui->tableWidget->removeRow(rowcount-1);
}
例:点击第4列的单元格,触发文件选择,并将选择的文件名设置到所点击的单元格中。
connect(ui->tableWidget, QTableWidget::cellClicked, [=](int row, int column){
qDebug() << "row=" << row << "column=" << column;
switch(column) {
case 4: //firmware
QString firmware = QFileDialog::getOpenFileName(this,"Firmware","","(*.*)");
if(!firmware.isNull()) {
qDebug() << "firmware:" << firmware;
ui->tableWidget->setItem(row, 4, new QTableWidgetItem(firmware));
}
break;
}
});
ui->lineEditModelName->setEnabled(false);
ui->lineEditModelName->setReadOnly(true);
ui->lineEditModelName->setFocusPolicy(Qt::NoFocus);