Qt学习笔记
本文最后更新于:2023年11月21日 中午
目录
1、创建第一个Qt程序
Create Project->Qt Widgets Application(创建一个Qt应用,包含一个基于qt设计师的主窗体)
->Location(不能有空格和中文,可以有下划线),**路径选择不能有中文(重要!!!)**->Build System(选择qmake,ps:一般的Qt工程你就直接使用qmake就可以了,cmake的强大功能一般人是用不到的 //参考的另一篇博客)->Details(QWidget是QDialog和QMainWindow的父类,Qwidget是空窗口,QMainWindow多了工具栏,QDialog是对话框),选择QWidget作为基类,取消Generate form使用代码编写。->Kits(选择套件)->Summary(finish)团队开发时,添加到版本控制系统(svn,vss,git)
main函数代码
#include "mywidget.h"
#include <QApplication>// 包含一个应用程序类的头文件
// main程序入口 argc命令行变量的数量 argv命令行变量的数组
int main(int argc, char *argv[])
{
QApplication a(argc, argv);// a应用程序对象,在qt中,有且仅有一个
MyWidget w;// 创建窗口对象,MyWidget的父类->QWidget
w.show();// 窗口对象 默认不会显示,必须调用show方法显示
return a.exec();//让应用程序对象a进入消息循环机制,等待用户点叉叉,使得窗口不会一闪而过,使代码阻塞到这一行
}
2、命名规范以及快捷键
.pro文件不要添加任何东西,除非你知道写的是什么。.pro文件就是工程文件,它是qmake自动生
成的用于生产makefile的配置文件。
QT += core gui //Qt包含的模块
greaterThan(QT_MAJOR_VERSION, 4): QT += widgets//大于4版本以上,包含widget模块
CONFIG += c++17
# You can make your code fail to compile if it uses deprecated APIs.
# In order to do so, uncomment the following line.
#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0
//源文件
SOURCES += \
main.cpp \
mywidget.cpp
//头文件 自动生成的
HEADERS += \
mywidget.h
Qt基本模块
mywidget.h
#ifndef MYWIDGET_H
#define MYWIDGET_H
#include <QWidget>//窗口类头文件 QWidget
class MyWidget : public QWidget
{
Q_OBJECT // Q_OBJECT宏,允许类中使用信号和槽的机制
public:
MyWidget(QWidget *parent = nullptr); // 有参构造函数
~MyWidget();
};
#endif // MYWIDGET_H
mywidget.cpp
#include "mywidget.h"
// 命名规范
// 类名 首字母大写,单词和单词之间首字母大写
// 函数名 变量名称 首字母小写,单词和单词之间首字母大写
// 快捷键
// 注释 ctrl + /
// 运行 ctrl + r
// 编译 ctrl + b
// 字体缩放 ctrl + 鼠标滚轮
// 查找 ctrl + f
// 整行移动 ctrl + shift + ⬆或者⬇
// 帮助文档 F1
// 自动对齐 ctrl + i
// 同名之间的.h和.cpp切换 F4
// 帮助文档,左侧的帮助;在Qt5.16\mingw49_32\bin的Qt助手
MyWidget::MyWidget(QWidget *parent)
: QWidget(parent)// 初始化列表
{
}
MyWidget::~MyWidget()
{
}
3、QPushBottom的创建
构造函数里创建
#include "mywidget.h"
#include <QPushButton>
MyWidget::MyWidget(QWidget *parent)
: QWidget(parent)// 初始化列表
{
// 创建一个按钮
QPushButton * btn = new QPushButton;
// btn->show();// show以顶层方式弹出窗口控件
// 让btn对象 依赖在 MyWdget窗口中
btn->setParent(this);
// 显示文本
btn->setText("first button");
// 创建第二个按钮 按照控件的大小创建窗口
QPushButton * btn2 = new QPushButton("second button",this);
// 重置窗口大小 长x宽
resize(600,400);
// 移动btn2按钮,设置坐标
btn2->move(100,100);
// 设置固定窗口大小,用户不能改变串窗口大小
setFixedSize(600,400);
// 设置窗口标题
setWindowTitle("第一个窗口");
}
MyWidget::~MyWidget()
{
}
4、对象树
父类先构造,子类先析构
在Qt中创建对象的时候会提供一个Parent对象指针。
QObject是以对象树的形式组织起来的。
当你创建一个QObject对象时候,会看到QObject的构造函数接收一个QObject指针作为参数,这个参数就是Parent,也就是父对象指针。
这相当于,在创建QObject对象时,可以提供一个其父对象,我们创建的这个QObject对象会自动添加到其父类对象的children()列表。
当父类对象析构的时候,这个列表中的所有对象也会被析构(注意:这里的父对象并不是继承意义的父类)
QWdget是能够在屏幕上显示的一切组件的父类。
QWidget继承自QObject,因此也继承了这种对象树关系。一个孩子自动地成为父组件的一个子组件。因此,它会显示在父组件的坐标系统中,被父组件的边界剪裁。例如,当用户关闭一个对话框的时侯,应用程序将共刑除,那么,我们希望属于这个对话框的按钮、图标等应该一起被迸除。事实就是如此,因为这些都是对话框的子组件。
MyPushButton类的创建
#ifndef MYPUSHBUTTON_H
#define MYPUSHBUTTON_H
#include <QPushButton>//继承QPushButton,没有这个选择就先选择继承它的父亲
class MyPushButton : public QPushButton
{
Q_OBJECT
public:
explicit MyPushButton(QWidget *parent = nullptr);
~MyPushButton();
signals:
};
#endif // MYPUSHBUTTON_H
#include "mypushbutton.h"
#include <QDebug>//打印输出
MyPushButton::MyPushButton(QWidget *parent)
: QPushButton(parent)//换父亲
{
qDebug()<<"我的按钮类构造调用";
}
MyPushButton::~MyPushButton()
{
qDebug()<<"我的按钮类析构调用";
}
打印先打印的是儿子的析构,但是是后面释放。
#include "mywidget.h"
#include <QPushButton>
#include <mypushbutton.h>
#include <QDebug>//打印输出
MyWidget::MyWidget(QWidget *parent)
: QWidget(parent)// 初始化列表
{
// 创建一个自己的按钮对象
MyPushButton *mybtn = new MyPushButton;
mybtn->setText("我自己的按钮");
mybtn->move(200,0);
mybtn->setParent(this);
qDebug()<<"MyWidget构造";
}
MyWidget::~MyWidget()
{
qDebug()<<"MyWidget析构";
}
总结:当创建的对象在堆区时候,如果指定的父亲是QObject派生下来的类或者QObject子类派生下来的类,**可以不用管理释放的操作(就是不用deletex)**,将对象会放入到对象树中。一定程度上简化了内存回收机制
5、Qt中的坐标系
左上角为(0,0),x向右增大,y向下增大
6、信号和槽
6.1 实现点击按钮关闭窗口
connect( 信号的发送者,发送的具体信号,信号的接受者,信号的处理(槽))
信号槽的优点:松散耦合,信号发送端和接受端本身是没有关联的,通过connect连接将两端耦合在一起。
#include "mywidget.h"
#include <QPushButton>
#include <mypushbutton.h>
#include <QDebug>//打印输出
MyWidget::MyWidget(QWidget *parent)
: QWidget(parent)// 初始化列表
{
// 创建一个自己的按钮对象
MyPushButton *mybtn = new MyPushButton;
mybtn->setText("我自己的按钮");
mybtn->move(200,0);
mybtn->setParent(this);
// 点击我的按钮,关掉窗口
// 参数1:信号的发送者,参数2:发送的具体信号(点击)函数的地址;参数3:信号的接受者this窗口,参数4:信号的处理(槽)函数地址
connect(mybtn,&MyPushButton::clicked,this,&MyWidget::close);
//connect(mybtn,&QPushButton::clicked,this,&QWidget::close);// 用父类的也可以
}
MyWidget::~MyWidget()
{
}
6.2 自定义的信号和槽
自定义信号:写到signals下;返回值是void,只需要声明,不需要实现;可以有参数,可以重载。
自定义槽:早期Qt槽函数必须写在public slot下,高级版本可以写道public或者全局下;返回值是void,需要声明,也需要实现;可以有参数,可以重载。
触发自定义信号:emit
#include "widget.h"
// Teacher 类 老师类
// Student 类 学生类
// 下课后,老师会触发一个信号,饿了,学生响应信号,请客吃饭
Widget::Widget(QWidget *parent)
: QWidget(parent)
{
// 创建老师和学生对象,并且指定父亲,就不用释放
this->zt = new Teacher(this);
this->st = new Student(this);
connect(zt,&Teacher::Hungry,st,&Student::treat);
// 调用下课,触发老师饿了,随后学生响应
classisover();
}
Widget::~Widget()
{
}
void Widget::classisover()
{
// 下课函数 调用后触发老师饿了信号
emit zt->Hungry();
}
6.3 自定义的信号和槽发生重载的解决
1.需要利用函数指针明确指向函数的地址,成员函数指针需要加上作用域
2.QString->char * 先转成QByteArray(.toUtf8())再转char*(),.data的返回值是char *
Widget代码
#include "widget.h"
// Teacher 类 老师类
// Student 类 学生类
// 下课后,老师会触发一个信号,饿了,学生响应信号,请客吃饭
Widget::Widget(QWidget *parent)
: QWidget(parent)
{
// 创建老师和学生对象,并且指定父亲,就不用释放
this->zt = new Teacher(this);
this->st = new Student(this);
//connect(zt,&Teacher::Hungry,st,&Student::treat);
// 调用下课,触发老师饿了,随后学生响应
//classisover();
// 函数指针->函数地址,&+函数名
void(Teacher::*teacherSignal)(QString) = &Teacher::Hungry;// 成员函数的函数指针
void(Student::*studentSlot)(QString) = &Student::treat;
// 当出现重载的时候,需要出现设置信号和槽的函数地址
connect(zt,teacherSignal,st,studentSlot);//重载出现二义性
classisover();
}
Widget::~Widget()
{
}
void Widget::classisover()
{
// 下课函数 调用后触发老师饿了信号,两个信号
emit zt->Hungry();
emit zt->Hungry("宫保鸡丁");
}
槽函数重载
#include "student.h"
#include <QDebug>
Student::Student(QObject *parent)
: QObject{parent}
{
}
void Student::treat()
{
qDebug()<<"请老师吃饭";
}
void Student::treat(QString foodname)// 重载treat
{
//打印QString类型有引号,要转成char*就没有引号
//qDebug()<<"请老师吃饭,老师要吃:"<<foodname;
// QString->char * 先转成QByteArray(.toUtf8())再转char*(),data的返回值是char *
qDebug()<<"请老师吃饭,老师要吃:"<<foodname.toUtf8().data();
}
信号重载
void Hungry();
void Hungry(QString foodname);
6.4 信号连接信号
connect(btn,&QPushButton::clicked,zt,teacherSignal);teacherSignal要换成无参形式,否则参数不匹配;
#include "widget.h"
#include <QPushButton>
// Teacher 类 老师类
// Student 类 学生类
// 下课后,老师会触发一个信号,饿了,学生响应信号,请客吃饭
Widget::Widget(QWidget *parent)
: QWidget(parent)
{
// 创建老师和学生对象,并且指定父亲,就不用释放
this->zt = new Teacher(this);
this->st = new Student(this);
//点击一个按钮,再下课,再触发老师饿了
QPushButton *btn = new QPushButton("下课",this);
this->resize(600,400); // 重置窗口大小
connect(btn,&QPushButton::clicked,this,&Widget::classisover);
//无参信号和槽连接
void(Teacher::*teacherSignal)(void) = &Teacher::Hungry;// 成员函数的函数指针
void(Student::*studentSlot)(void) = &Student::treat;
connect(zt,teacherSignal,st,studentSlot);
// 信号连接信号 之间跳过下课,按钮直接使老师饿了
connect(btn,&QPushButton::clicked,zt,teacherSignal);
// 断开信号
//disconnect(zt,teacherSignal,st,studentSlot);
}
Widget::~Widget()
{
}
void Widget::classisover()
{
// 下课函数 调用后触发老师饿了信号,两个信号
emit zt->Hungry();
emit zt->Hungry(“宫保鸡丁”);
}
6.5 Qt4版本信号连接
1.信号可以连接信号;
2.一个信号可以连接多个槽函数;
3.多个信号可以连接同一个槽函数;
4.信号和槽函数的参数,必须一一对应;
5.信号的参数个数可以多于槽函数的参数个数,但是类型要一一对应;
clicked的参数是bool类型,teacherSignal如果是QString参数就不是一一对应,如果是void参数就是信号的参数比槽函数的参数多,所以不会报错。
6.Qt4:connect(zt,SIGNAL(hungry()),st,SLOT(treat(QString));参数直观,但是不做类型检测,不推荐。
6.5 Lambda表达式
C++11中的Lambda表达式用于定义并创建匿名函数对象,以简化编程工作。
表达式:[函数对象参数](操作符重载函数参数)mutable->返回值(函数体)
① “=”为值传递,“&”为地址传递,a为只对a可见;
② mutable关键字,用于修饰值传递的变量,修改拷贝而不是本体;
③ int ret = [ ]( )->int {return 100;}();使得ret=100;
Widget::Widget(QWidget *parent)
: QWidget(parent)
{
QPushButton *btn = new QPushButton;
this->resize(600,400); // 重置窗口大小
btn->setText("close");
btn->setParent(this);//把按钮安到窗口上
//利用lambda表达式实现关闭按钮
connect(btn,&QPushButton::clicked,this,[=](){
this->close();
btn->setText("aaa");
});
}
6.6 信号槽的总结
任务:设计一个窗口,两个按钮,点击open打开另一个窗口,点击close关闭窗口。
#include "widget.h"
#include "ui_widget.h"
#include <QPushButton>
Widget::Widget(QWidget *parent)
: QWidget(parent)
, ui(new Ui::Widget)
{
ui->setupUi(this);
QPushButton *btn = new QPushButton;
btn->setText("open");
btn->setParent(this);
resize(600,400);
QPushButton *btn2 = new QPushButton;
btn2->setText("close");
btn2->setParent(this);
btn2->move(200,200);
QWidget *w2=new QWidget;
connect(btn,&QPushButton::clicked,w2,&QWidget::show);
connect(btn2,&QPushButton::clicked,w2,&QWidget::close);
}
Widget::~Widget()
{
delete ui;
}
任务:设计一个窗口,一个按钮,点击open打开另一个窗口,open变成close,再点击close关闭窗口,close变成open。
#include "widget.h"
#include "ui_widget.h"
#include <QPushButton>
Widget::Widget(QWidget *parent)
: QWidget(parent)
, ui(new Ui::Widget)
{
ui->setupUi(this);
QPushButton *btn = new QPushButton;
btn->setText("open");
btn->setParent(this);
resize(600,400);
QWidget *w1 = new QWidget;
connect(btn,&QPushButton::clicked,w1,[=](){
if(btn->text()=="open")
{
btn->setText("close");
w1->show();
}
if(btn->text()=="close")
{
btn->setText("open");
w1->close();
}
});
}
Widget::~Widget()
{
delete ui;
}
7、QMainWindow
7.1 菜单栏和工具栏
1.菜单栏最多只有一个,工具栏可以有多个
2.QMenu,QToolBar
#include "mainwindow.h"
#include <QMenuBar>
#include <QToolBar>
#include <QPushButton>
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
{
// 重置窗口大小
resize(600,400);
// 菜单栏的创建 最多只有一个
QMenuBar *bar = menuBar();// 本身在对象树
setMenuBar(bar); // 将菜单栏放入窗口中
QMenu *fileMenu = bar->addMenu("文件"); // 创建菜单
QMenu *editMenu = bar->addMenu("编辑");
QAction * newAction = fileMenu->addAction("新建");// 创建菜单项
// 添加分割线
fileMenu->addSeparator();
QAction * newAction1 = fileMenu->addAction("打开");
editMenu->addAction("复制");
// 工具栏的创建 可以有多个
QToolBar *toolBar = new QToolBar(this);
addToolBar(Qt::LeftToolBarArea,toolBar);//默认在左边
// 只允许左右停靠
toolBar->setAllowedAreas(Qt::LeftToolBarArea | Qt::RightToolBarArea);
// 设置浮动
toolBar->setFloatable(false);
// 设置移动,bool值设置是否可以移动,相当于总开关
toolBar->setMovable(false);
// 设置内容
toolBar->addAction(newAction);
toolBar->addSeparator();
toolBar->addAction(newAction1);
// 工具栏添加控件
QPushButton* btn = new QPushButton("aa",this);
toolBar->addWidget(btn);
}
MainWindow::~MainWindow()
{
}
7.2 状态栏、铆接部件、核心部件
1.QStatusBar,QDockWidget(浮动窗口),QTextEdit;
// 状态栏
QStatusBar* stBar = statusBar();
setStatusBar(stBar);//设置到窗口中
//放标签控件
QLabel *label = new QLabel("提示信息",this);
stBar->addWidget(label);
QLabel *label2 = new QLabel("右侧提示信息",this);
stBar->addPermanentWidget(label2);
// 铆接部件(浮动窗口)可以有多个
QDockWidget *dockWidget = new QDockWidget("浮动",this);
addDockWidget(Qt::BottomDockWidgetArea,dockWidget);
// 只允许上下
dockWidget->setAllowedAreas(Qt::TopDockWidgetArea | Qt::BottomDockWidgetArea);;
//设置中心部件,只能一个
QTextEdit *edit = new QTextEdit(this);
setCentralWidget(edit);
8、资源文件的添加
1. 将图片文件拷贝到项目位置;
2. 右键项目->添加新文件->Qt->Qt recourse File->给资源文件起名
3. rec生成rec.qrc
4. open in editor打开文件
5. 添加前缀 添加文件,编译
6. 使用“:+前缀名+文件名”
9、模态和非模态对话框创建
1. 模态对话框:不可以对其他窗口进行操作;QDialog dlg(this);dlg.exec();
2. 非模态对话框:可以对其他窗口进行操作;QDialog *dlg2 = new QDialog(this);dlg2->show();
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QDialog>
#include <QDebug>
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::MainWindow)
{
ui->setupUi(this);
// 点击新建按钮 弹出会话框
connect(ui->actionnew,&QAction::triggered,[=](){
//对话框 分类
// 模态对话框(不可以对其他窗口进行操作) 非模态对话框(可以对其他窗口进行操作)
QDialog dlg(this);
dlg.resize(200,100);
dlg.exec();//模态方式创建,阻塞功能
qDebug()<<"模态对话框弹出了";
// 非模态对话框
QDialog *dlg2 = new QDialog(this);//存在内存泄漏风险,创建堆区
dlg2->resize(200,100);
dlg2->show();
dlg2->setAttribute(Qt::WA_DeleteOnClose);//设置属性,差掉就释放内存
qDebug()<<"非模态对话框弹出了";
});
}
MainWindow::~MainWindow()
{
delete ui;
}
10、消息对话框
QMessageBox 静态成员函数 创建对话框
错误、信息、提问、警告
利用返回值来判断用户的选择
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QDialog>
#include <QDebug>
#include <QMessageBox>
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::MainWindow)
{
ui->setupUi(this);
// 点击新建按钮 弹出会话框
connect(ui->actionnew,&QAction::triggered,[=](){
//消息对话框
//QMessageBox::critical(this,"critical","错误");//错误对话框
//QMessageBox::information(this,"info","信息");//信息对话框
//提问对话框
//参数1:父亲,参数2:标题;参数3:提示内容;参数4:按键类型;参数5:默认关联回车按键
// QMessageBox::question(this,"ques","提问",QMessageBox::Save|QMessageBox::Cancel,QMessageBox::Cancel);
// if(QMessageBox::Save == QMessageBox::question(this,"ques","提问",QMessageBox::Save|QMessageBox::Cancel,QMessageBox::Cancel))
// {
// qDebug()<<"选择了保存";
// }
// else
// {
// qDebug()<<"选择了取消";
// }
//警告对话框
QMessageBox::warning(this,"warning","警告");
});
}
MainWindow::~MainWindow()
{
delete ui;
}
11、其他对话框
QColorDialog,QFileDialog,QFontDialog
// 点击新建按钮 弹出会话框
connect(ui->actionnew,&QAction::triggered,[=](){
//颜色对话框
// QColor color = QColorDialog::getColor(QColor(255,0,0));
// qDebug()<<"r = "<<color.red()<<"g = "<<color.green()<<"b = "<<color.blue();
//文件对话框,参数1:父亲 参数2:名字 参数3:路径 参数4:过滤文件格式
// QString str = QFileDialog::getOpenFileName(this,"打开文件","E:\\BaseFile\\senior\\C++work","(*.doc)");
// qDebug()<<str;
bool flag;
QFont font = QFontDialog::getFont(&flag,QFont("华文彩云",32));
qDebug()<<font.family();
});
12、登陆窗口布局
1. 实现登录窗口;
2. 利用布局方式 给窗口进行美化;
3. 选取widget进行布局,水平布局、垂直布局、栅格布局;
4. 给用户名、密码、登录、退出按钮进行布局;
5. 默认窗口和控件之间有9间隙,可以调整 layoutLeftMargin;
6. 利用弹簧进行布局。
13、控件
13.1 按钮组
1. QPushButton 常用按钮;
2. QToolButton 工具按钮;用于显示图片,如图想显示文字,修改风格;ToolButtonStyle;
3. radioButton 单选按钮,设置默认选择ui->woman->setChecked(true);
4. checkbox 多选按钮,监听状态,2是选中,1是半选,0是未选。
Widget::Widget(QWidget *parent)
: QWidget(parent)
, ui(new Ui::Widget)
{
ui->setupUi(this);
//设置单选按钮,男默认选中
ui->woman->setChecked(true);
//多选按钮,0表示为选择,2表示选中
connect(ui->cBox,&QCheckBox::stateChanged,[=](int state){
qDebug()<<state;
});
}
13.2 QListWidget控件
QListWidget 列表容器:QListWidgetItem 显示一行内容;
设置居中方式setTextAlignment(),通过查询assitant帮助文档查询参数。
// 利用listWidget写诗
// QListWidgetItem *item = new QListWidgetItem("一川烟雨,满城风絮,梅子黄时雨");
// ui->listWidget->addItem(item);//放到listWidget控件里
// item->setTextAlignment(Qt::AlignCenter);//水平居中
//QStringList QList<QString>
QStringList list;
list<<"陌上花开"<<"可缓缓归矣";
ui->listWidget->addItems(list);
13.3 QTreeWidget控件
1. 设置水平头 setHeaderLabels();
2. 创建根节点 QTreeWidgetItem *item1 = new QTreeWidgetItem(QStringList()<<”力量”);
3. 添加根节点到树控件 ui->treeWidget->addTopLevelItem(item1);
4. 添加子节点 item1->addChild(l1);
#include "widget.h"
#include "ui_widget.h"
Widget::Widget(QWidget *parent)
: QWidget(parent)
, ui(new Ui::Widget)
{
ui->setupUi(this);
// treeWidget
// 设置水平头
ui->treeWidget->setHeaderLabels(QStringList()<<"英雄"<<"英雄介绍");
QTreeWidgetItem *item1 = new QTreeWidgetItem(QStringList()<<"力量");//匿名对象
QTreeWidgetItem *item2 = new QTreeWidgetItem(QStringList()<<"敏捷");
QTreeWidgetItem *item3 = new QTreeWidgetItem(QStringList()<<"智力");
// 加载顶层的节点
ui->treeWidget->addTopLevelItem(item1);
ui->treeWidget->addTopLevelItem(item2);
ui->treeWidget->addTopLevelItem(item3);
//追加子节点
QStringList heroL1,heroL2,heroL3;
heroL1<<"200";
heroL2<<"100";
heroL3<<"130";
QTreeWidgetItem *l1 = new QTreeWidgetItem(heroL1);
QTreeWidgetItem *l2 = new QTreeWidgetItem(heroL2);
QTreeWidgetItem *l3 = new QTreeWidgetItem(heroL3);
item1->addChild(l1);
item2->addChild(l2);
item3->addChild(l3);
}
Widget::~Widget()
{
delete ui;
}
13.4 QTableWidget控件
#include "widget.h"
#include "ui_widget.h"
Widget::Widget(QWidget *parent)
: QWidget(parent)
, ui(new Ui::Widget)
{
ui->setupUi(this);
// TableWidget控件
// 设置列数
ui->tableWidget->setColumnCount(3);
// 设置水平表头
ui->tableWidget->setHorizontalHeaderLabels(QStringList()<<"姓名"<<"性别"<<"年龄");
// 设置行数
ui->tableWidget->setRowCount(5);
// 设置正文
//ui->tableWidget->setItem(0,0,new QTableWidgetItem("亚瑟"));
QStringList namelist;
namelist<<"亚瑟"<<"赵云"<<"王昭君"<<"关羽"<<"花木兰";
QList<QString> sexList;
sexList<<"男"<<"男"<<"女"<<"男"<<"女";
for(int i = 0; i < 5; i++)
{
int col = 0;
ui->tableWidget->setItem(i,col++,new QTableWidgetItem(namelist[i]));
ui->tableWidget->setItem(i,col++,new QTableWidgetItem(sexList.at(i)));//at越界抛异常
//int 转QString
ui->tableWidget->setItem(i,col++,new QTableWidgetItem(QString::number(i+18)));
}
}
Widget::~Widget()
{
delete ui;
}
13.5 其他控件介绍
1. stackedWidget控件
2. 下拉框控件comboBox
3. QLabel显示图片和gif
#include "widget.h"
#include "ui_widget.h"
#include <QMovie>
Widget::Widget(QWidget *parent)
: QWidget(parent)
, ui(new Ui::Widget)
{
ui->setupUi(this);
// 栈控件使用
// 欢迎按钮
// 设置默认页面
ui->stackedWidget->setCurrentIndex(0);
connect(ui->btn_welcome,&QPushButton::clicked,[=](){
ui->stackedWidget->setCurrentIndex(0);
});
// 编辑按钮
connect(ui->btn_edit,&QPushButton::clicked,[=](){
ui->stackedWidget->setCurrentIndex(1);
});
// 项目按钮
connect(ui->btn_project,&QPushButton::clicked,[=](){
ui->stackedWidget->setCurrentIndex(2);
});
// 下拉框
ui->comboBox->addItem("奔驰");
ui->comboBox->addItem("宝马");
ui->comboBox->addItem("自行车");
connect(ui->btn_bike,&QPushButton::clicked,[=](){
//ui->comboBox->setCurrentIndex(2);
ui->comboBox->setCurrentText("自行车");
});
// 利用QLabel显示图片和gif动态图片
ui->lb1->setPixmap(QPixmap(":/Image/1.jpg"));
QMovie *movie = new QMovie(":/Image/m.gif");
ui->lb1->setMovie(movie);//嵌入到lbl
movie->start();//动起来
}
Widget::~Widget()
{
delete ui;
}
14、自定义控件
1、添加新文件,Qt->设计师界面类(.cpp .h .ui)
2、.ui中设计 QSpinBox和QSlider两个控件
3、Widget中使用自定义控件,拖拽一个Widget,点击提升为,点击添加,点击提升,将.ui变成一个smallWidget类
4、在smallWidget.cpp实现功能,改变数字,滑动条跟着移动,信号槽监听
5、提供两个按钮,对ui的smallWidget实例对象进行操作
#include "widget.h"
#include "ui_widget.h"
#include <QDebug>
Widget::Widget(QWidget *parent)
: QWidget(parent)
, ui(new Ui::Widget)
{
ui->setupUi(this);
// 点击获取控件当前值
connect(ui->btn_set,&QPushButton::clicked,[=](){
qDebug()<<ui->widget->getNum();
});
connect(ui->btn_half,&QPushButton::clicked,[=](){
ui->widget->setNum(50);
});
}
Widget::~Widget()
{
delete ui;
}
15、Qt的鼠标事件
1、鼠标进入事件enterEvent
2、鼠标离开事件leaveEvent
3、鼠标移动 mouseMoveEvent
4、鼠标按下 mousePressEvent
5、鼠标释放 mouseReleaseEvent
6、ev->x(),ev->y()
7、ev->button() 可以判断所有按键,Qt::LeftButton,Qt::RightButton
8、ev->buttons() 判断组合按键,判断用 &
9、格式化字符串 QString str = QString(“%1 %2 %3 …”).arg().arg().arg()…
#include "mylabel.h"
#include <QDebug>
#include <QMouseEvent>
myLabel::myLabel(QWidget *parent)
: QLabel{parent}
{
//设置鼠标追踪状态,默认是false
setMouseTracking(true);
}
void myLabel::enterEvent(QEvent *event)
{
qDebug()<<”鼠标进入”;
}
void myLabel::leaveEvent(QEvent *)
{
qDebug()<<”鼠标离开”;
}
void myLabel::mouseMoveEvent(QMouseEvent *ev)//持续过程
{
// if(ev->buttons() & Qt::LeftButton)//同真才为真
// {
QString str = QString("鼠标移动了,x = %1 y = %2 globalx = %3 globaly = %4").arg(ev->x()).arg(ev->y()).arg(ev->globalX()).arg(ev->globalY());
qDebug()<<str;
// }
}
void myLabel::mousePressEvent(QMouseEvent *ev)//瞬间
{
// if(ev->button() == Qt::LeftButton)//左键才打印
// {
QString str = QString("鼠标按下了,x = %1 y = %2 globalx = %3 globaly = %4").arg(ev->x()).arg(ev->y()).arg(ev->globalX()).arg(ev->globalY());
qDebug()<<str;
// }
}
void myLabel::mouseReleaseEvent(QMouseEvent *ev)//瞬间
{
// if(ev->button() == Qt::LeftButton)//左键才打印
// {
QString str = QString("鼠标释放了,x = %1 y = %2 globalx = %3 globaly = %4").arg(ev->x()).arg(ev->y()).arg(ev->globalX()).arg(ev->globalY());
qDebug()<<str;
// }
}
16、定时器
1、利用事件void timerEvent(QTimerEvent *e)
2、启动定时器 startTimer(1000)毫秒单位
3、timerEvent的返回值是定时器定时器的唯一标识,可以和 e->timerId 做比较
4、利用定时器类 QTimer
5、先创建定时器对象,启动定时器start(毫秒)
6、每隔一定毫秒,发送信号timeout,进行监听
#include "widget.h"
#include "ui_widget.h"
#include <QTimer>
Widget::Widget(QWidget *parent)
: QWidget(parent)
, ui(new Ui::Widget)
{
ui->setupUi(this);
// 启动定时器 单位是毫秒
id1 = startTimer(1000);
id2 = startTimer(2000);
//定时器第二种方式
QTimer *timer = new QTimer(this);
//启动定时器
timer->start(500);//0.5s进入中断
connect(timer,&QTimer::timeout,[=](){
static int num = 1;
//每0.5s加1;
ui->label_4->setText(QString::number(num++));
});
connect(ui->stop,&QPushButton::clicked,[=](){
timer->stop();
});
}
Widget::~Widget()
{
delete ui;
}
void Widget::timerEvent(QTimerEvent *e)
{
//label_2 每隔1s +1
if(e->timerId()==id1)
{
static int num1 = 1;
ui->label_2->setText(QString::number(num1++));
}
//label_3 每隔2s +1
if(e->timerId()==id2)//判断定时器
{
static int num2 = 1;
ui->label_3->setText(QString::number(num2++));
}
}
17、event 事件分发器和事件过滤器
1、用于时间的分发,也可以做拦截(不建议)
2、bool event(QEvent *e)返回值是true代表永华处理这个事件,不向下分发
3、e->type() == 鼠标按下
bool myLabel::event(QEvent *e)
{
if(e->type() == QEvent::MouseButtonPress)//鼠标按下,在事件event事件中做拦截操作
{
QMouseEvent *ev = static_cast<QMouseEvent*>(e);//将e转换为ev类型
QString str = QString("event中,,鼠标按下了,x = %1 y = %2 globalx = %3 globaly = %4").arg(ev->x()).arg(ev->y()).arg(ev->globalX()).arg(ev->globalY());
qDebug()<<str;
return true;//代表用户自己处理事件,不向下分发
}
//其他事件交给父类处理
return QLabel::event(e);
}
---------------------------------------------------------------------------------
bool Widget::eventFilter(QObject *obj,QEvent *e)
{
if(obj == ui->label)
{
if(e->type() == QEvent::MouseButtonPress)//鼠标按下,在事件event事件中做拦截操作
{
QMouseEvent *ev = static_cast<QMouseEvent*>(e);//将e转换为ev类型
QString str = QString("事件过滤器中,,鼠标按下了,x = %1 y = %2 globalx = %3 globaly = %4").arg(ev->x()).arg(ev->y()).arg(ev->globalX()).arg(ev->globalY());
qDebug()<<str;
return true;//代表用户自己处理事件,不向下分发
}
}
// 其他默认处理
return QWidget::eventFilter(obj,e);
}
18、QPainter
18.1 绘图事件
1、绘图事件 void paintEvent()
2、声明一个画家对象
void Widget::paintEvent(QPaintEvent *)
{
//实例化画家对象 this指定的是绘图设备
QPainter painter(this);
//设置画笔
QPen pen(QColor(255,0,0));
//设置画笔宽度
pen.setWidth(3);
//设置画笔风格
pen.setStyle(Qt::DotLine);
//让画家使用这个笔
painter.setPen(pen);
//设置画刷
QBrush brush(Qt::cyan);
//设置画刷风格
brush.setStyle(Qt::Dense7Pattern);
//让画家使用画刷
painter.setBrush(brush);
//划线
painter.drawLine(QPoint(0,0),QPoint(100,100));
//画圆 椭圆
painter.drawEllipse(QPoint(100,100),50,50);
}
18.2 绘图高级设置
1、抗锯齿,效率低
2、对画家进行移动,保存状态,还原状态
void Widget::paintEvent(QPaintEvent *)
{
QPainter painter(this);
painter.drawEllipse(QPoint(100,50),50,50);
//设置抗锯齿能力 效率低
painter.setRenderHint(QPainter::Antialiasing);
painter.drawEllipse(QPoint(200,50),50,50);
//画矩形
painter.drawRect(QRect(20,20,50,50));
//让画家移动位置
painter.translate(100,0);
//保存画家状态
painter.save();
//画另一个矩形
painter.drawRect(QRect(20,20,50,50));
painter.translate(100,0);
//还原画家状态
painter.restore();
painter.drawRect(QRect(20,20,50,50));
}
18.3 手动调用绘图事件
如果想手动调用绘图事件,利用update,利用画家画图片painterDrawPixmap
Widget::Widget(QWidget *parent)
: QWidget(parent)
, ui(new Ui::Widget)
{
ui->setupUi(this);
//移动
connect(ui->btn_move,&QPushButton::clicked,[=](){
//如果要手动调用绘图事件,用update更新
update();
posx += 20;
});
}
void Widget::paintEvent(QPaintEvent *)
{
QPainter painter(this);
//如果超过屏幕,重新开始
if(posx > this->width())
{
posx = 0;
}
painter.drawPixmap(posx,0,QPixmap(":/Image_1/10.jpg"));
}
18.4 绘图设备
1. QPixmap QImage QBitmap(黑白)QPicture QWidget
2. QPixmap 对不同平台做了显示优化
3. QImage可以对像素进行访问
4. QPicture可以记录和重现绘图指令
#include "widget.h"
#include "ui_widget.h"
#include <QPixmap>
#include <QPainter>
#include <QImage>
#include <QPicture>
Widget::Widget(QWidget *parent)
: QWidget(parent)
, ui(new Ui::Widget)
{
ui->setupUi(this);
// //Pixmap绘图设备 专门为平台做了显示的优化
// QPixmap pix(400,400);
// QPainter painter(&pix);
// //填充颜色
// pix.fill(Qt::white);
// painter.setPen(QPen(Qt::blue));
// painter.drawEllipse(QPoint(200,200),100,100);
// //保存到磁盘
// pix.save("E:\\pix.png");
//QImage 绘图设备 可以对像素进行访问
// QImage img(300,300,QImage::Format_RGB666);
// img.fill(Qt::white);
// QPainter painter(&img);
// painter.setPen(QPen(Qt::blue));
// painter.drawEllipse(QPoint(200,200),100,100);
// img.save("E:\\img.png");
//QPicture 绘图设备 可以记录和重新绘图指令
QPicture pic;
QPainter painter;
painter.begin(&pic);//开始往pic画
painter.setPen(QPen(Qt::cyan));
painter.drawEllipse(QPoint(150,150),100,100);
painter.end();//结束画图
pic.save("E:\\pic.zt");
}
void Widget::paintEvent(QPaintEvent *event)
{
//利用QImage对像素点修改
// QPainter painter(this);
// QImage img;
// img.load(":/Image_1/10.jpg");
// //修改像素点
// for(int i = 50;i<100;i++)
// {
// for(int j = 50; j<100;j++)
// {
// QRgb value = qRgb(255,0,0);
// img.setPixel(i,j,value);
// }
// }
// painter.drawImage(0,0,img);
//重现QPicture的绘图指令
QPainter painter(this);
QPicture pic;
pic.load("E:\\pic.zt");
painter.drawPicture(0,0,pic);
}
19、QFile文件读写操作
文件QFile和文件信息读写QFileInfo
Widget::Widget(QWidget *parent)
: QWidget(parent)
, ui(new Ui::Widget)
{
ui->setupUi(this);
//点击选取文件按钮,弹出文件对话框
connect(ui->btn_file,&QPushButton::clicked,[=]()
{
QString path = QFileDialog::getOpenFileName(this,"打开文件","E:\\1.Qt_temporary_files");
//将路径放入到lineEdit
ui->lineEdit->setText(path);
//编码格式类
//QTextCodec *codec = QTextCodec::codecForName("gbk");
//读取内容,放入textEdit中
QFile file(path);//参数就是读取文件的路径
//设置打开方式
file.open(QIODevice::ReadOnly);
//QByteArray array = file.readAll();
//按行读取
QByteArray array;
while(!file.atEnd())
{
array += file.readLine();
}
//将读入的数据放入textEdit
ui->textEdit->setText(array);
//转成gbk格式,默认是utf-8格式
//ui->textEdit->setText(codec->toUnicode(array));
//对文件对象进行关闭
file.close();
//进行写文件
// file.open(QIODevice::Append);//用追加的方式进行写
// file.write("aaaaaa");
// file.close();
//QFileInfo读取文件信息
QFileInfo info(path);
qDebug()<<"大小:"<<info.size()<<"后缀名:"<<info.suffix()<<"文件名:"<<info.fileName();
qDebug()<<"创建日期:"<<info.birthTime().toString("yyyy/MM/dd hh:mm:ss");
});
}
20、翻金币项目
https://blog.csdn.net/q5120192609/article/details/127470422
转载就当作是自己的(