QT入门笔记
声明:本文档部分内容参考自网络(用作笔记),如有侵权可联系笔者删除。
QtCreater5.9安装和下载
下载链接: 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中添加资源文件
- 将资源文件(图片等)放到项目路径下。
- 右键项目->添加新文件 -> Qt -> Qt resourse file -> 给资源文件取名为"src"
- 生成src.qrc
- 右键src.qrc->open in editor->添加
- 添加前缀->添加文件
- 使用“:+前缀名+文件名”
利用ui进行界面布局
例:实现登录界面
- 利用Container中的Widget对其中的控件进行布局:水平布局、垂直布局、栅格布局
- 例如:登录界面中的“用户名”和“密码"的提示信息可以使用Label控件来显示。
- 例如:登录界面中的“用户名输入框”和“密码输入框"的输入框可以使用LineEdit控件来显示。
- 例如:登录界面中的密码输入框,可以通过设置"echoMode"属性为passward来进行密文显示。
- 例如:“登录”、"注册"的按钮可以使用“PushButton”来显示。
- 例如:“用户名”和“密码"的提示信息以及输入框,可以使用栅格布局来进行布局
- 例如:“登录”、"注册"的按钮可以使用水平布局来进行布局。
- 例如:控件被拉升后,可以使用弹簧Spacers来进行填充。
布局图

效果图

创建第一个QT项目
工程文件(.pro)
#-------------------------------------------------
#
# 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
main.cpp (QT程序入口)
#include "mywidget.h"
#include <QApplication> // 包含一个应用程序类的头文件
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;
    *}
    **/
}
mywidget.cpp (自定义的类源码)
#include "mywidget.h"
myWidget::myWidget(QWidget *parent)
    : QWidget(parent) //初始化列表
{
}
myWidget::~myWidget()
{
}
mywidget.h (自定义的类头文件)
#ifndef MYWIDGET_H
#define MYWIDGET_H
#include <QWidget>
class myWidget : public QWidget
{
    Q_OBJECT	//允许类中使用信号和槽机制
public:
    myWidget(QWidget *parent = 0); //构造函数,默认参数
    ~myWidget(); //析构函数
};
#endif // MYWIDGET_H
Qt的模块
- Qt Widgets
 窗口模块,大于4版本的QT才有该模块,4之前该部分归为Gui模块。
- Qt Core
- Qt Gui
- Qt WebKit
- Qt Network
- Qt SQL
 QT数据库模块
- Qt MulitMedia
- Qt Mulitmedia Widgets
- Qt QML
- Qt Quick
- Qt Quick Controls
- Qt Quick Dialogs
- Qt Test
QT的对象树

 qt使用对象树,简化了资源释放的操作(QObject派生的类)。
 通过setParent函数将Qt中的对象添加到对象树中。
析构的顺序: 在析构当前对象时,执行当前对象的析构函数,在当前对象的析构函数中,会寻找当前对象的子对象;即,先析构所有子对象,再析构当前对象。自下而上的顺序。
Qt的窗口坐标系
–>x
 |
 |/
 y
左上角为原点,水平方向往右为x轴正半轴;垂直方向往下为y轴正半轴。
QT的基类
QWidget: 最简单的窗口什么都没有。
 QMainWindow:带有简单菜单栏、状态栏等的窗口
 QDialog:对话框(一般不带,最小化和最大化的按钮,一般带有选择性的按钮,如“确认”,“去取消”等)
上述3个基类之间的关系:
 QMainWindow继承自QWidget。
 QDialog继承自QWidget。
 即:
 QWidget是QMainWindow和QDialog的父类。
QWidget
常用API
设置窗口的大小
resize(宽,高);
 setFixedsize(宽,高);
设置窗口标题
setWindowTitile("文本");
Qt 获取当前编译时间,并设置标题
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

菜单栏(MenuBar)
在QMainWindow中菜单栏有且仅有一个。
在QMainWindow中创建菜单栏
QMenuBar *mbar = MenuBar()
初始化菜单栏
setMenuBar(mbar)
在菜单栏中创建菜单
QMenu *fileMenu = addMenu("文件")
在菜单中创建菜单项
QAction *newAction = mbar->addAction("新建")
在菜单项与菜单项之间添加分隔线
mbar->addseparator()
工具栏(QToolBar)
在QMainWindow中工具栏可以有多个
创建工具栏
QToolBar *toolBar = new QToolBar(this);
在QMainWindow中添加工具栏
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)
最多只有一个
创建状态栏
QStatusBar *sbar = statusBar()
设置状态栏到窗口中
setStatusBar(sbar)
添加信息到左侧
sbar->addWidget(label);
添加信息到右侧
sbar->addPermanentWidget(label2);
铆接部件 (QDockWidget)
创建铆接部件
QDockWidget *dwt = QDockWidget("浮动窗口",this)
添加铆接部件到QMainWindow中并设置默认停靠位置
addDockWidget(Qt::RightDockWidgetArea,dwt);
设置停靠范围
dwt->setAllowedAreas(Qt::RightDockWidgetArea | Qt::TopDockWidgetArea);
设置中心部件(只能有一个)
QTextEdit *edit = new QTextEdit(this);
setCentralWidget(edit);
QDialog
对话框有两种分类:模态对话框,非模态对话框
模态对话框
不可以操作其它窗口
 创建
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,继承自QDialog)
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","你好!");
颜色对话框(QcolorDialog)
	QColor color = QColorDialog::getColor(QColor(0,255,0));
    qDebug() << "r = " << color.red() << "g = " << color.green() << "b = " << color.blue();
文件对话框(QFileDialog)
QString str  = QFileDialog::getOpenFileName(this,"title","C:","(*.txt)");
qDebug() << str;
参数1: 父亲
 参数2:标题
 参数3:默认打开的文件夹路径
 参数4:指定显示的文件后缀
 返回值:打开的文件的路径。
字体对话框(QFontDialog)
			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类
常用API
创建一个按钮
 QpushButton *btn = new QpushButton;
设置父对象
 btn->setparent(this);
设置按钮的文本
btn->setText("按钮1");
移动按钮的位置
btn->move(宽,高);
设置按钮的大小
可以使用父类QWidget中设置大小的函数。
Qt的信号与槽机制
阿拉丁神灯:
 人 摩擦 --> 灯 出灯神
 【信号的发送者】 【要发送的信号】 【信号的接收者】 【信号的处理(槽函数)】
 在Qt中,使用connect函数来实现:
 connect(信号的发送者, 发送的信号, 信号的接收者, 处理的槽函数);
 信号与槽的优点:松散耦合,将本没有关联的 “信号的发送者”、“信号”、“信号的接收者”、“处理槽函数”之间关联起来。
 例如:
 connect(ptrCloseButton, &QPushButton::clicked, this, &QWidget::close);
 可以查看对象的类,寻找信号,寻找处理槽函数。
函数
connect(ptrCloseButton, &QPushButton::clicked, this, &QWidget::close);
 参数1:信号的发送者
 参数2:信号
 参数3:信号的接收者
 参数3:处理的槽函数
自定义信号与槽
自定义信号的写法(规定)
- 要写到类的头文件中的signal:属性下。
- 返回值是void
- 只需要声明,不需要实现
- 可以有参数,可以重载
自定义槽函数的写法(规定)
- 早期的Qt版本,必须写到public solt属性下,高版本可以写到public或者全局下。
- 返回值是void
- 需要声明,需要实现
- 可以有参数,可以重载
注意事项
- 当信号与槽函数重载时,使用函数指针来明确是哪一个具体的信号和槽函数。
- 信号也可以连接信号。(通过信号直接触发另一个信号)
- 一个信号可以连接多个槽函数或者信号。
- 多个信号可以连接同一个槽函数。
- 信号与槽函数的参数的类型必须一一对应(顺序和参数类型必须一致)。
- 信号中的参数个数可以多余槽函数的参数个数(类型必须一一对应)。
- 信号连接信号时,注意两个信号的参数也要符合第5和第6的规则。(前一个信号的参数可以多于被后一个信号,并一一对应)
案例
下课后,老师饿了,学生
例1: 自定一个信号:饿了
#ifndef TEACHER_H
#define TEACHER_H
#include <QObject>
class Teacher : public QObject
{
    Q_OBJECT
public:
    explicit Teacher(QObject *parent = nullptr);
signals:
	void hungry();
	void hungry(QString string);
public slots:
};
#endif // TEACHER_H
例2:自定义一个槽函数:请客
#ifndef STUDENT_H
#define STUDENT_H
#include <QObject>
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 <QDebug>
student::student(QObject *parent) : QObject(parent)
{
}
void student::treat()
{
    qDebug() << "请客吃饭";
}
例3:实现信号触发函数
在触发函数中使用emit 触发信号。
void myWidget::classIsOver()
{
    emit tch->hungry();
}
在主函数中实现信号与槽的连接并触发信号
main()
{
	//...
     connect(tch, &Teacher::hungry, stu, &student::treat);
     classIsOver();
	//...
}
断开信号与槽
disconnect(信号的发送者,信号, 信号的接收者, 处理的槽函数);
 断开信号与槽。
Qt4的信号与槽函数的连接方式
connect(zt, SIGNAL(hungry(), st, SLOT(treat()));
- Qt4版本方式的有优点:参数直观。
- 缺点:类型不作检测。
lambda表达式(匿名表达式)
格式
[capture](parametres)mutable->return-type
{
	statement
}
/*
[函数对象参数](操作符重载函数参数)mutable->返回值
{
	函数体
}
*/
详解
[]
 
标志着lambda表达式的开始,不能省略!
[]中可以传入参数
 
- 空: 当参数为空时,没有使用任何函数对象参数。
- =: 函数体可以使用lambda所在作用域范围内可见的局部变量(包括this),值传递方式。
- &: 函数体可以使用lambda所在作用域范围内可见的局部变量(包括this),引用传递方式。
- this: 函数体可以使用lambda所在类中的成员变量。
- 局部变量名: 指定传递哪一个局部变量,值传递。
- &局部变量名: 指定传递哪一个局部变量,引用传递。
- 局部变量名,&局部变量名: 值传递第一个局部变量,引用传递第二个局部变量。
- = ,局部变量名,&局部变量名:除了指定了传输方式的两个局部变量之外,其它都用值传递。
- & ,局部变量名,&局部变量名:除了指定了传输方式的两个局部变量之外,其它都用引用传递。
()
 
标志着操作符重载的函数参数,当不存在参数时,可以省略。参数可按值传递,也可以引用传递。
mutable
mutable声明,可以省略。加上mutable修饰符之后,可以修改按值传递进来的拷贝(注意是拷贝,而不是本身)。
lambda表达式的调用:
[capture](parametres)mutable->return-type
{
	statement
}();
//使用lambda表达式作为槽函数时,信号的接收者可以省略.
connect(信号的发送者, 信号,[=](){
	this->close();
});
使用lambda表达式作为槽函数时,信号的接收者可以省略
信号与槽总结

常用控件
按钮组
QPushButton
常用按钮,一般用于显示文字
QToolButton
常用按钮,默认显示图片(Icon)可以修改属性:toolButtonStyle为ToolButtonBesideIcon。凸起风格:autoRaise
QRadioButton
单选按钮,可以使用GroupBox来将单选按钮进行分组。
 使用setChecked(true)默认选中
QCheckBox
多选按钮,可以使用GroupBox来将多选按钮进行分组。
 监听状态,stateChanged(int state),
 state 0: 未选中
 state 1: 半选(表示旗下有多个子多选按钮,当旗下没有全选时,显示该状态。)
 state 2: 选中
QComboBox(下拉选择框)
QComboBox清楚/添加内容
清除内容
	ui->comboBox->clear();
	ui->comboBox->addItem(QString(name));
QComboBox设置默认内容(默认选择)
    ui->comboBox->setCurrentIndex(2);
QComboBox 内容改变事件
void (QComboBox::*signalCurrentIndexChanged)(int) = &QComboBox::currentIndexChanged;
    connect(ui->comboBox,signalCurrentIndexChanged,[=](int index){
        qDebug() << "comboBoxModelSelect Changed:" << index;
        if(index >= 0) {
        	// handle
        }
    });
QComboBox 暂停/恢复信号触发
暂停信号触发
ui->comboBox->blockSignals(true);
恢复信号触发
ui->comboBox->blockSignals(false);
Item Views
基于模型的控件,例如数据库模型
 其中包含:List View、Tree View、 Table View、 Column View等。
Item Widgets
基于内容的 Widget
ListWidget
对于ListWidget而言,其中的每一行都是QListWidgetitem *item类型的对象。
QListWidgetitem *item = new QListWidgetitem("锄禾日当午");
ui->listWidget->additem(QListWidgetitem);
item->setTextAlignment(Qt::AlignmentCenter);
QStringList list;
list << "锄禾日当午" << "汗滴禾下土" << "谁之盘中餐" << "粒粒皆辛苦";
ui->listWidget->additems(QStringList);
TreeWidget
QTableWidget
QTableWidget初始化
	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();
QTableWidget添加内容
	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 ++;
    }
QTableWidget设置单元格不可更改(不可编辑)
            QTableWidgetItem* pItem = ui->tableWidget->item(i, j);
            pItem->setFlags(pItem->flags() & (~Qt::ItemIsEditable));
QTableWidget删除所有内容
	while (ui->tableWidget->rowCount()>0)
	{
	    ui->tableWidget->removeRow(0);
	}
QTableWidget 获取当前选中行(支持获取多行)
	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
                }
            }
	}
QTableWidget插入行
默认从选中行之前插入,选中几行,则插入几行,并且自动更新行序号;无选中行,则从最后的行尾插入,并且自动更新行序号。
		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("")));
        }
QTableWidget删除行
默认删除选中行,选中几行,则删除几行,并且自动更新行序号;无选中行,则删除最末行,并且自动更新行序号。
		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);
        }
QTableWidget单元格点击事件
例:点击第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;
        }
    });
QLineEdit
设置不可修改的机种方式
- 鼠标不可选择,无变化
ui->lineEditModelName->setEnabled(false);
- 鼠标可选,变化
ui->lineEditModelName->setReadOnly(true);
- 鼠标不可选,无变化
ui->lineEditModelName->setFocusPolicy(Qt::NoFocus);









