QT的介绍
跨平台的C++图形用户界面应用程序框架
linux 桌面环境
知识点一、QT创建
创建流程
1. application
QT widgets Apllication
2. 配置选择
2.1 位置
英文 无空格
2.2 Build System
2.3 详细信息
基类选择
QWidget 空窗口
QMainWindow (多了菜单栏)
QDialog (多了对话框)
2.4 Traslation
2.5 Kits
选择配置版本
2.6 summary
版本控制 多人合作
主要生成文件
.pro 工程文件
不轻易修改 双击打开项目
main.cpp
程序入口
mywidget.cpp
mywidget.h
.ui
可视化设计界面
生成的exe文件运行–提示缺少dll 文件
解决方法
cmd 跳转到该文件下
windeployqt 01_FirstProject.exe
程序:pro工程文件
QT += core gui //包含的模块 core 与 gui 模块
greaterThan(QT_MAJOR_VERSION, 4): QT += widgets //当版本大于4 加入 widgets 模块
CONFIG += c++11
# 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 \
widget.cpp
//头文件---自动生成
HEADERS += \
widget.h
FORMS += \
widget.ui
# Default rules for deployment.
qnx: target.path = /tmp/$${TARGET}/bin
else: unix:!android: target.path = /opt/$${TARGET}/bin
!isEmpty(target.path): INSTALLS += target
程序:main.cpp
#include "widget.h"
#include <QApplication>// 应用程序类的头文件
int argc 命令行变量数量 char *argv[] 命令行变量数组
int main(int argc, char *argv[])
{
QApplication a(argc, argv);//应用程序对象a 有且只有一个
Widget w; //继承QWidgetlei
w.show(); //展示窗口
return a.exec(); //进入消息循环机制 阻塞功能 保留窗口 使其不一闪而过
//相当于死循环 当有触发时跳出循环
}
程序:mywidget.h
#ifndef MYWIDGET_H
#define MYWIDGET_H
#include <QWidget>//包含头文件 窗口类
class myWidget : public QWidget
{
Q_OBJECT // 宏 运行使用信号与槽
public:
myWidget(QWidget *parent = nullptr);
~myWidget();
};
#endif // MYWIDGET_H
程序:mywidget.cpp
#include "mywidget.h"
myWidget::myWidget(QWidget *parent)
: QWidget(parent)//初始化列表
{
}
myWidget::~myWidget()
{
}
命名规范与常用快捷键
命名规范
类名: 首字母大写
变量、函数名 : 首字母小写 单词和单词之间首字母 大写
快捷键:
运行 ctrl + R
编译 ctrl + B
查询 ctrl + F
注释 ctrl + /
缩放 ctrl + 滑轮
整行代码移动 ctrl + shfit + ↑
自动对齐 ctrl + i
帮助 F1
同名文件切换 F4
知识点二、添加一个系统自带按钮
QPushButton
qmake: Qt += widgets 所属模块
Inherits: 父类
Inherited By:子类
mywidget.cpp
坐标系
左上角为(0,0)点
#include "mywidget.h"
#include <QPushButton>
myWidget::myWidget(QWidget *parent)
: QWidget(parent)
{
//设置窗口属性
//重置窗口大小
resize(600,400); //宽 高
//固定大小不能缩放
setFixedSize(600,400);
//设置窗口标题
setWindowTitle("第一个窗口");
//创建按钮
//创建一个按钮
QPushButton * btn = new QPushButton;
//btn->show(); //以顶层的方式弹出
btn -> setParent(this);//设置一个父亲
btn -> setText("第一个按钮");
//创建二个按钮
QPushButton * btn2 = new QPushButton("第二个按钮",this);
//移动按钮
btn2->move(100,0);
}
myWidget::~myWidget()
{
}
知识点三、对象树
自动释放子类对象 自动回收内存
释放顺序:
1.先释放子类 在释放父类
添加自定义的按钮
添加一个C++ class
命名
添加一个基类 如果没有 选择一个 基类 然后手动调整为QPushButton
mywidget.h
#ifndef MYWIDGET_H
#define MYWIDGET_H
#include <QWidget>
#include <QDebug>//打印头文件
#include <QPushButton>
#include "mypushbutton.h"
class myWidget : public QWidget
{
Q_OBJECT
public:
myWidget(QWidget *parent = nullptr);
~myWidget();
};
#endif // MYWIDGET_H
mywidget.cpp
#include "mywidget.h"
myWidget::myWidget(QWidget *parent)
: QWidget(parent)
{
//07对象树
MyPushButton * myBtn = new MyPushButton;
myBtn->setParent(this);
myBtn->setText("退出");
myBtn->move(275,150);
}
myWidget::~myWidget()
{
qDebug() << "mywidget析构调用";//实际释放时先释放子类对象 但打印时 该程序先打印 在跳转到子类对象中去
}
mypushbutton.h
#ifndef MYPUSHBUTTON_H
#define MYPUSHBUTTON_H
//#include <QWidget>
#include <QPushButton> // 改变继承对象
class MyPushButton : public QPushButton// 改变继承对象
{
Q_OBJECT
public:
explicit MyPushButton(QWidget *parent = nullptr);// 指针无需改变 父类指针指向子类对象
~MyPushButton();
signals:
};
#endif // MYPUSHBUTTON_H
mypushbutton.cpp
#include "mypushbutton.h"
#include <QDebug>
MyPushButton::MyPushButton(QWidget *parent) : QPushButton(parent)// 改变继承对象
{
qDebug() << "我的按钮类构造调用";
}
MyPushButton::~MyPushButton()
{
qDebug() << "我的按钮类析构调用";
}
知识点四、信号与槽
主要内容:
1、了解系统自带的信号与槽
2、自定义信号与槽
3、自定义的信号和槽发生重载的解决拓展提升:
4.1.信号可以连接信号
4.2.一个信号 可以绑定多个槽函数
4.3.多个信号 可以连接 同一个槽函数
4.4.信号和槽函数 必须类型一一匹配
4.5.信号参数个数可多于槽函数lambda 表达式的运用
//作用
C++中: Lambda表达式就是:能嵌入到其他表达式当中的匿名函数(闭包)
QT中 : 异步调用
信号与槽
signal 信号
QAbstractButton信号
Slots槽
按钮 点击 窗口 关闭窗口
信号的发送者 发送的具体信号 信号的接受者 信号的处理(槽)
优点:松散耦合 发送者 与 接受者 没有关联
connect() 耦合
//信号和槽
//参数1 信号的发送者 参数2 发送的信号(函数地址) 参数3 信号的接受者 参数4 处理的槽信号
connect(myBtn, &MyPushButton::clicked, this, &myWidget::close);
自定义信号与槽
案例一:
内容描述:
下课了 老师发出 饿了的信号
学生接受信号 执行 请老师吃饭操作添加类:
如果没有需要继承的类 使用 QObject 方便使用对象树 释放对象
自定义信号 teacher.h
#ifndef TEACHER_H
#define TEACHER_H
#include <QObject>
class Teacher : public QObject
{
Q_OBJECT
public:
explicit Teacher(QObject *parent = nullptr);
signals:
//自定义信号 写到signlas 下
//返回void 只需要声明 不需要实现
//可以有参数 可以重载
void hungry();
void hungry(QString foodName);
};
#endif // TEACHER_H
teacher.cpp
#include "teacher.h"
Teacher::Teacher(QObject *parent) : QObject(parent)
{
}
自定义类 student.h
#ifndef STUDENT_H
#define STUDENT_H
#include <QObject>
class Student : public QObject
{
Q_OBJECT
public:
explicit Student(QObject *parent = nullptr);
void treat();
void treat(QString foodName);
signals:
//public slots:
//早期槽函数 必须卸载该模块下
//返回值void 需要声明 也需要实现。
};
#endif // STUDENT_H
student.cpp
#include "student.h"
#include<QDebug>
Student::Student(QObject *parent) : QObject(parent)
{
}
void Student::treat()
{
qDebug() << "请老师吃饭";
}
void Student::treat(QString foodName)
{
// 打印 QString 类型会加上引号 解决方法
// 先转成 QByteArray(QT下的字节数组) 再转成 char *
qDebug() << "请老师吃饭,老师要吃" << foodName.toUtf8().data();
}
widget.h
#ifndef MYWIDGET_H
#define MYWIDGET_H
#include <QWidget>
#include "teacher.h"
#include "student.h"
#include<QDebug>
#include<QPushButton>
class Widget : public QWidget
{
Q_OBJECT
public:
Widget(QWidget *parent = nullptr);
~Widget();
private:
Teacher * t1;
Student * s1;
void classIsOver1();
void classIsOver2();
};
#endif // MYWIDGET_H
widget.cpp
#include "widget.h"
Widget::Widget(QWidget *parent)
: QWidget(parent)
{
//固定大小不能缩放
setFixedSize(600,400);
//信号与槽
this->t1 = new Teacher(this);//老师对象
this->s1 = new Student(this);//学生对象
// connect(t1,&Teacher::hungry,s1,&Student::treat);
// 有重载时会发生歧义 信号与槽 为同一个地址 需要改为一下形式 函数指针明确指向对象 2.自定义的信号和槽发生重载的解决
qDebug() << "调用无参函数";
void(Teacher:: *teacherSignal)(void) = &Teacher::hungry;
void(Student:: *studentSlot)(void) = &Student::treat;
connect(t1,teacherSignal,s1,studentSlot);
classIsOver1();//触发函数1
qDebug() << "调用有参函数";
void(Teacher:: *teacherSignal2)(QString) = &Teacher::hungry;
void(Student:: *studentSlot2)(QString) = &Student::treat;
connect(t1,teacherSignal2,s1,studentSlot2);
classIsOver2();//触发函数2
//点击按钮触发槽函数
//信号连接槽
QPushButton * btn1 = new QPushButton("下课了1",this);
connect(btn1,&QPushButton::clicked,s1,studentSlot);
//connect(btn1,&QPushButton::clicked,s1,studentSlot2); 4.4 4.5
//链接 cliked 含有 bool 类型参数 可以提供给 void槽 但不能提供给有参函数
//信号连接信号1
QPushButton * btn2 = new QPushButton("下课了2",this);
btn2->move(100,0);
connect(btn2,&QPushButton::clicked,t1,teacherSignal);
//disconnect(t1,teacherSignal,s1,studentSlot); //断开连接
//信号连接信号函数2 这里触发两次
QPushButton * btn3 = new QPushButton("下课了3",this);
btn3->move(200,0);
connect(btn3,&QPushButton::clicked,this,&Widget::classIsOver2);
//disconnect(t1,teacherSignal2,s1,studentSlot2); //断开连接
}
void Widget::classIsOver1()
{
emit t1->hungry();
}
void Widget::classIsOver2()
{
emit t1->hungry("宫爆鸡丁");
}
Widget::~Widget()
{
}
Lambda表达式
// lambda 表达式
//作用
/*异步调用*/
//语法测试 [=] 值传递 [&] 引用传递 [变量] 只传递该变量
QPushButton * btn4 = new QPushButton;
[=] () {
btn4 -> setParent(this);//设置一个父亲
btn4->setText("111");
btn4->move(0,100);
}();
QPushButton * myBtn1 = new QPushButton(this);
QPushButton * myBtn2 = new QPushButton(this);
myBtn1->move(0,200);
myBtn2->move(100,200);
int m = 20;
connect(myBtn1,&QPushButton::clicked,this,[m]() mutable{m = 100 + 10;qDebug() << m;});
connect(myBtn2,&QPushButton::clicked,this,[=]() {qDebug() << m;});
qDebug() << m;
//指定返回值类型
int ret = []() -> int{return 1000;}();
qDebug() << "ret = " << ret;
//利用lambda 表达式关闭窗口
QPushButton * btn5 = new QPushButton(this);
btn5 -> setText("关闭");
btn5->move(300,300);
connect(btn5,&QPushButton::clicked,this,[=](){
this->close();
emit t1->hungry();});
作业
实现关闭与打开
#include "widget.h"
#include "ui_widget.h"
Widget::Widget(QWidget *parent)
: QWidget(parent)
, ui(new Ui::Widget)
{
ui->setupUi(this);
setWindowTitle("作业");
resize(500,500);
QWidget*one=new QWidget;
QPushButton*brt1=new QPushButton;
brt1->setParent(this);
brt1->move(100,200);
brt1->setParent(this);
brt1->setText("open");
QPushButton*brt2=new QPushButton;
brt2->setParent(this);
brt2->move(300,200);
brt2->setParent(this);
brt2->setText("close");
QPushButton*brt3=new QPushButton;
brt3->setParent(this);
brt3->move(200,300);
brt3->setParent(this);
brt3->setText("open");
connect(brt1,&QPushButton::clicked,one,[=](){
one->show();
if(brt3->text()=="open")
{
brt3->setText("close");
}
});
connect(brt2,&QPushButton::clicked,one,[=](){
one->close();
if(brt3->text()=="close")
{
brt3->setText("open");
}
});
connect(brt3,&QPushButton::clicked,one,[=](){
if(brt3->text()=="close")
{
one->close();
brt3->setText("open");
}
else
{
one->show();
brt3->setText("close");
}
});
}
Widget::~Widget()
{
delete ui;
}
知识点五、QMainWindow各个组成部分
菜单栏QMenuBar
最多能有一个
#include<QMenuBar>//菜单栏
//菜单栏创建 只能有一个
QMenuBar * bar = menuBar();
//将菜单栏放入到窗口中
setMenuBar(bar);
//创建菜单
QMenu * fileMenu = bar->addMenu("文件");
QMenu * editMenu = bar->addMenu("编辑");
//菜单项
QAction * newAction = fileMenu->addAction("新建");
//添加分隔符
fileMenu->addSeparator();
//菜单项
QAction * openAction = fileMenu->addAction("打开");
工具栏QToolBar
可以有多个
可以添加控件
#include<QToolBar>//工具栏
#include<QPushButton>//按钮控件
/***************************************************************/
//工具栏 可以有多个
QToolBar * toolBar = new QToolBar(this);
addToolBar(Qt::LeftToolBarArea,toolBar);//枚举值 左侧悬挂
//设置工具栏可以拖动的位置
toolBar->setAllowedAreas(Qt::LeftToolBarArea|Qt::RightToolBarArea);
//设置能否浮动
toolBar->setFloatable(false);
//设置总开关 能否移动
toolBar->setMovable(false);
//工具栏中的内容
toolBar->addAction(newAction);
toolBar->addSeparator();
toolBar->addAction(openAction);
//工具栏中添加控件
QPushButton * btn = new QPushButton("aa", this);
toolBar->addWidget(btn);
状态栏 QStatusBar
1
#include<QStatusBar>//状态栏
#include<QLabel>//标签控件
//转态栏 最多有一个
QStatusBar * stBar = statusBar();
//设置到窗口中
setStatusBar(stBar);
//放标签控件
QLabel * label = new QLabel("提示信息",this);
stBar->addWidget(label); //左侧提示
QLabel * label2 = new QLabel("右侧提示信息",this);
stBar->addPermanentWidget(label2);//右侧提示
中心部件setCentralWidget
只能有一个
#include<QTextEdit>//文本编辑 用作记事本
//设置中心部件
QTextEdit * edit = new QTextEdit(this);
setCentralWidget(edit);
铆接部件QDockWidget
添加浮动窗口
可以有多个
#include<QDockWidget>//浮动窗口
//铆接部件 浮动窗口 可以有多个
QDockWidget * dockWidget = new QDockWidget("浮动",this);//标题
//设置停靠位置 上面
addDockWidget(Qt::TopDockWidgetArea,dockWidget);
//设置后期停靠 只允许上下
dockWidget->setAllowedAreas(Qt::TopDockWidgetArea | Qt::BottomDockWidgetArea);
知识点六、UI界面
MainWindow基本内容添加
MainWindow
自带部分控件,其他需自己添加
menuBar
1.添加menu
2.添加actionnew (需要先写英文,再将text属性改为想要的)
toolBar
添加
将menuBar的ationnew拖拽到这里拓展实现界面
缺点:
只能实现静态场景
Dock Widget
知识点七、Edit控件
LineEdit : 用于单行文本输入。
TextEdit: 用于多行文本输入,显示。也可以显示HTML格式文本。
PlainTextEdit:需要与文本进行处理的方法
知识点八、添加资源文件(图片)
第一种方法:
绝对路径
第二种方法:
添加资源文件
01.将文件放入项目目录下
02.创建资源文件
右键项目 添加新文件 QT recourse 给资源文件起名
03 新文件操作
打开
添加前缀(用作区分)
> 添加资源(全选)
04 使用资源
" : + 前缀名 + 文件名"
ui->setupUi(this);
//绝对路径
//ui->actionnew->setIcon(QIcon("D:/my_code/vsc/QT/02_QTsource/Image/Luffy.png"));
//":+前缀名+文件名"
ui->actionnew->setIcon(QIcon(":/Image/Luffy.png"));
ui->actionnew_2->setIcon(QIcon(":/Image/LuffyQ.png"));
知识点九、对话框
模态和非模态对话框
#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() << " 模态对话框弹出了!!";}
);
//非模态对话框
connect(ui->actionnew_2,&QAction::triggered,[=](){
// 需要建立在堆区 否则会因为没有阻塞功能 而lambda表达式实际上为匿名函数,
//否则一闪而过
QDialog *dlg2 = new QDialog(this);//默认整个程序关闭时释放 否则内存满了
dlg2->setAttribute(Qt::WA_DeleteOnClose);//设置了 属性 关闭时释放
dlg2->resize(200,100);
dlg2->show();
qDebug() << " 非模态对话框弹出了!!"; }
);
}
MainWindow::~MainWindow()
{
delete ui;
}
消息对话框
#include<QMessageBox>
//消息对话框
connect(ui->actionnew_3,&QAction::triggered,[=](){
//错误对话框
//QMessageBox::critical(this,"ctritical","错误");
//信息对话框
//QMessageBox::information(this,"info","信息");
//提问对话框
//参数1:父亲 参数2:标题 参数3:内容 参数4:按键类型 参数5:默认关联回车按键
// QMessageBox::question(this,"ques","提问",QMessageBox::Save|QMessageBox::Cancel,QMessageBox::Cancel);
//警告对话框
QMessageBox::warning(this,"warning","警告");}
);
其他标准对话框
#include<QColorDialog>
#include<QFileDialog>
#include<QFontDialog>
//其他对话框
connect(ui->actionnew_3,&QAction::triggered,[=](){
//颜色对话框
//QColor color = QColorDialog :: getColor(QColor(255,0,0));
//qDebug() << "r = " << color.red() << " g = " << color.green() << "b = " << color.blue() << endl;
//文件对话框 参数1 父亲 参数2 标题 参数3 路径 参数4 过滤的文件类型
// 返回文件的路径
// QString str = QFileDialog::getOpenFileName(this,"打开文件","C:\\Users\\weng\\Desktop","(*.txt)");
//qDebug() << str;
//字体对画框
//bool flag;//bool值标志
QFont font = QFontDialog::getFont(&flag,QFont("华为彩云",36));
qDebug() << "字体: " << font.family().toUtf8().data() << "字号:" << font.pointSize() << "是否倾斜: " << font.bold() << "是否倾斜" << font.italic() << endl;
}
);
知识点十、UI窗口布局
widget 对齐布局
UI设计 对齐
布局方式一:Widget1、红色为还未布局
2、布局方式二:效果不好
Layouts
将控件拖入Widget 然后右键布局
垂直
水平
栅格 多行多列 使用
调整大小
调整间隙(控件之间默认留有间隙)
弹簧布局
控制间距
调整大小
Expanding 伸缩
fix 固定
知识点十一、组件介绍
Line Edit控件
Label组件
按钮组
Push Button
按钮
Tool Button
实现头像 右边是用户名
icon 选择资源
toolButtonStyle 设置图标文字显示形式
autorise 凸起效果
Radio Button
单选按钮
利用Group Box 放入同一组内
1.默认选中某个按钮
2.选中后打印信息
ui->setupUi(this);
//设置单选按钮
ui->radioButton->setChecked(true);
//信号与槽
connect(ui->radioButton,&QRadioButton::clicked,[=](){
qDebug() << "选中了男的!";
});
connect(ui->radioButton_2,&QRadioButton::clicked,[=](){
qDebug() << "选中了女的!";
});
Check Button
多选按钮
tristate 开启 半选选项
代码
//设置多选按钮
// 2是选中 0 是未选中 1 是半选
connect(ui->checkBox,&QCheckBox::stateChanged,[=](int state){
qDebug() << state;
});
QListWidget组件
列表容器
//利用listWidget写诗
//方式一
QListWidgetItem * item = new QListWidgetItem("醋和日当午");
ui->listWidget->addItem(item);
item->setTextAlignment(Qt::AlignHCenter);//居中
//方式二
QStringList list;
list << "汗滴禾下土" << "谁知盘中餐" << "粒粒皆辛苦" ;
ui->listWidget->addItems(list);
QTreeWidget树控件
//利用treeWidget 写阶梯结构
//写水平头
ui->treeWidget->setHeaderLabels(QStringList()<<"英雄"<<"英雄介绍");//用到了匿名对象语法
QTreeWidgetItem * liItem = new QTreeWidgetItem(QStringList()<<"力量");
//加载顶层的节点
ui->treeWidget->addTopLevelItem(liItem);
//追加子节点
QStringList hero1;
hero1 << "德玛西亚" << "社会主义万岁!!";
QTreeWidgetItem * l1 = new QTreeWidgetItem(hero1);
liItem->addChild(l1);
QTableWidget控件
//利用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[i]));
//int 转 string
ui->tableWidget->setItem(i,col++,new QTableWidgetItem(QString::number(i+18)));
}
其他控件
Group Box 分组
Scroll Area 滚动
Tool Box 列表(类似于QQ列表)
Tab Widget 网页
Stacked Widget 切换页面Widget 用来布局
Frame 边框comboBox 下拉框
Line Edit 单行文本
Text Edit 多行文本
Plain Text Edit 纯文本
Spin Box 数字加减
Double Spin Box
Time edit 时间Horizontal Scroll Bar 水平滚动条
Horizontal Slider
Vertical Scroll Bar 垂直滚动条
Vertical Slider
Scroll Area
Tool Box 列表(类似于QQ列表)
Tab Widget 网页
Stacked Widget
//栈空间使用
//设置默认值
ui->stackedWidget->setCurrentIndex(0);
//通过按钮切换
connect(ui->pushButton_9,&QPushButton::clicked,this,[=](){
if(ui->stackedWidget->currentIndex() == 0)
{
ui->stackedWidget->setCurrentIndex(1);
}
else
{
ui->stackedWidget->setCurrentIndex(0);
}
});
comboBox 下拉框
//下拉框
ui->comboBox->addItem("本田");
ui->comboBox->addItem("丰田");
ui->comboBox->addItem("宝马");
ui->comboBox->setCurrentText("本田");
connect(ui->pushButton_10,&QPushButton::clicked,this,[=](){
//ui->comboBox->setCurrentIndex(2);
ui->comboBox->setCurrentText("宝马");
});
知识点十二、自定义控件
1创建 Qt设计师界面类 或者 C++Class 创建一个Qwidget类
一者用 UI 一者用 代码自定义空间2.在主界面 创建 widget 控件
3.提升 注意 类名是否正确
右键提升
添加
提升4.连接
实现功能1
1.1创建 Qt设计师界面类 或者 C++类
2.在主界面 创建 widget 控件
3.提升 注意 类名是否正确
4.实现功能数值变换
ui->setupUi(this);
//QSpinBox数值改变 QSlider 移动
void(QSpinBox:: * spSignal) (int) = &QSpinBox::valueChanged;//发生了重载 指定为 int 类型 才能使用setVlaue对应
connect(ui->spinBox, spSignal,ui->horizontalSlider,&QSlider::setValue);
//QSlider移动 QSpinBox数值改变
connect(ui->horizontalSlider,&QSlider::valueChanged,ui->spinBox,&QSpinBox::setValue);
//自定义控件中编写函数
//设置数值
void smallWidget::setNum(int num)
{
ui->spinBox->setValue(num);
}
//获取数值
int smallWidget::getNum()
{
return ui->spinBox->value();
}
ui->setupUi(this);
//点击获取
connect(ui->btn_get,&QPushButton::clicked,this,[=](){
qDebug () << ui->widget ->getNum();
});
connect(ui->btn_set,&QPushButton::clicked,this,[=](){
ui->widget->setNum(50);
});
知识点十三、Qt中的鼠标事件
1.需要创建自定义控件
1.1 创建一个 QWidget 类
手动改成对应的类 例如改为QLabel (注意QLabel 为需要被提升的控件的类)----一般三个地方需要改。
1.2 提升
1.3 编写 myLabel的代码
鼠标操作
//鼠标**进入事件**
void **enterEvent(QEvent *event)**;
//鼠标**离开事件**
void **leaveEvent(QEvent *)**;
//鼠标**按下**
virtual void **mousePressEvent(QMouseEvent *ev)**;
//鼠标**释放**
virtual void **mouseReleaseEvent(QMouseEvent *ev)**;
//鼠标**移动**
virtual void **mouseMoveEvent(QMouseEvent *ev);
mylabel.h
#ifndef MYLABEL_H
#define MYLABEL_H
#include <QLabel>
#include <QEvent>
#include <QEnterEvent>
#include <QDebug>
class myLabel : public QLabel
{
Q_OBJECT
public:
explicit myLabel( QWidget *parent = nullptr);
//鼠标进入事件
void enterEvent(QEvent *event);
//鼠标离开事件
void leaveEvent(QEvent *);
//鼠标按下
virtual void mousePressEvent(QMouseEvent *ev);
//鼠标释放
virtual void mouseReleaseEvent(QMouseEvent *ev);
//鼠标移动
virtual void mouseMoveEvent(QMouseEvent *ev);
signals:
};
#endif // MYLABEL_H
mylabel.cpp
#include "mylabel.h"
myLabel::myLabel(QWidget*parent) : QLabel(parent)
{
//设置鼠标追踪 无需要按下就能记录鼠标发生移动了
setMouseTracking(true);
}
//鼠标进入事件
void myLabel::enterEvent(QEvent *event)
{
qDebug() << "鼠标进入了";
}
//鼠标离开事件
void myLabel::leaveEvent(QEvent *)
{
qDebug() << "鼠标离开了";
}
//鼠标按下
void myLabel::mousePressEvent(QMouseEvent *ev)
{
if (ev->button() == Qt::LeftButton)//左键按下
{
// %1 表示参数位置 .arg() 表示参数
// x y 表示基于窗口位置 globalX gloablY 表示基于屏幕位置
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)
{
qDebug() << "鼠标释放了";
}
//鼠标移动
//移动状态条件判断(持续过程)
//持续过程存在 左键按下时 还可能存在其他按键情况
//buttons 联合按键 包含三种按键状态 左 中 右
void myLabel::mouseMoveEvent(QMouseEvent *ev)
{
//ev->buttons()
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;
}
qDebug() << "鼠标移动了";
}
知识点十四、定时器
方式一
1.先重写定时器事件 timerEvent
2.再启动定时器 id1 = startTimer(1000);方式二(利用定时器的类)
1.实例化对象 timer = new QTimer(this);
2.启动定时器 timer->start(500);
3.槽
widget.h
#ifndef WIDGET_H
#define WIDGET_H
#include <QWidget>
#include <QDebug>
#include<QTimer>
QT_BEGIN_NAMESPACE
namespace Ui { class Widget; }
QT_END_NAMESPACE
class Widget : public QWidget
{
Q_OBJECT
public:
Widget(QWidget *parent = nullptr);
~Widget();
//重写定时器事件
virtual void timerEvent(QTimerEvent *ev);
private:
Ui::Widget *ui;
int id1;
int id2;
};
#endif // WIDGET_H
widget.cpp
#include "widget.h"
#include "ui_widget.h"
Widget::Widget(QWidget *parent)
: QWidget(parent)
, ui(new Ui::Widget)
{
ui->setupUi(this);
//启动定时器的第一种方式 单位毫秒 返回定时器标志 标志属于奶一个定时器
//启动定时器
id1 = startTimer(1000);
id2 = startTimer(2000);
//qDebug() << id1 << id2;
//创建定时器的第二种方式
QTimer * timer = new QTimer(this);
//启动定时器
timer->start(500);
connect(timer,&QTimer::timeout,[=]()
{
static int num3 = 1;
ui->label_4->setText(QString::number(num3++));
});
connect(ui->pushButton, &QPushButton::clicked,[=](){
timer->stop();
});
}
Widget::~Widget()
{
delete ui;
}
//重写定时器事件
void Widget::timerEvent(QTimerEvent *ev)
{
qDebug() << ev-> timerId();
if(ev-> timerId() == id1)
{
static int num = 1;
ui ->label_2->setText(QString::number(num++));
}
if(ev-> timerId() == id2)
{
static int num2 = 1;
ui ->label_3->setText(QString::number(num2++));
}
}
知识点十五、event事件
事件分发器
app
bool event(QEvent *ev) 事件的分发
mousePressEvennt (鼠标按下时间) mouseMoveEvent(鼠标移动事件) timerEvent(定时器事件)
这里只是示意:
1.这里展示他有拦截功能 -暂时没有成功还是会出现
2.本质上启到分发的功能
bool myLabel::event(QEvent *e)
{
//如果是鼠标按下 在event事件分发中做拦截操作、、
if(e->type() == QEvent::MouseButtonPress)
{
QMouseEvent * ev = static_cast<QMouseEvent * >(e);//静态类型转换
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 QLabel::event(e);
}
事件过滤器
在程序将事件分发到分发器前进行拦截
//给label 安装事件过滤器
//步骤1 安装事件过滤器
ui->label->installEventFilter(this);
//步骤2 重写事件过滤器事件
//重写时间过滤器
bool Widget::eventFilter(QObject * obj,QEvent * e)
{
if(obj == ui->label)
{
if(e->type() == QEvent::MouseButtonPress)
{
QMouseEvent * ev = static_cast<QMouseEvent * >(e);//静态类型转换
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;
}
}
}
知识点十六、绘图
绘图事件
0.重写绘图事件
//绘图事件
void paintEvent(QPaintEvent * );
//绘图事件
void Widget::paintEvent(QPaintEvent * )
{
}
1.设置画家对象
QPainter painter(this);
画笔操作
// 设置画笔
QPen pen(QColor(255,0,0));
// 设置画笔宽度
pen.setWidth(3);
// 设置画笔风格
pen.setStyle(Qt::DotLine);
// 让画家使用该画笔
painter.setPen(pen);
// 画线
painter.drawLine(QPoint(0,0),QPoint(100,100));
// 画圆
painter.drawEllipse(QPoint(100,100),50,50);
// 画矩形
painter.drawRect(QRect(20,20,50,50));
// 画文字
painter.drawText(QRect(10,200,100,50),"好好学习");
//
画刷操作
// 设置画刷
QBrush brush(Qt::cyan);
// 设置画刷风格
brush.setStyle(Qt::Dense7Pattern);
// 让画家使用画刷
painter.setBrush(brush);
高级设置
抗锯齿操作
抬起画笔
保存画家状态,
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));
手动调用绘图事件
//点机按钮移动
connect(ui->pushButton,&QPushButton::clicked,[=]()
{
x += 20;
update();//在此触发画图事件
});
///利用画家添加资源图片///
QPainter painter(this);
//超出屏幕 从0开始
if(x > this->width())
{
x = 0;
}
painter.drawPixmap(x,0,QPixmap(":/Image/Luffy.png"));
绘图设备
QWidget 也属于绘图设备
QPainter painter(this); 这里this 指向QWidget
绘图设备是继承QPainterDevice的子类
QPixmap专门为图像在屏幕上的显示做了优化.
QBitmap是QPixmap的一个子类,颜色深度为1.
QImage专门为图像的像素级访问做了优化。
QPicture则可以记录和重现QPainter的各条命令。
Pixmap 绘图设备
//Pixmap 绘图设备
QPixmap pix(300,300);//背景大小
//填充颜色(画布)
pix.fill(Qt::white);
//声明画家
QPainter painter(&pix);
painter.setPen(QPen(Qt::green));//绿色
painter.drawEllipse(QPoint(150,150),100,100);//画圆
//保存
pix.save("D:\\pix.png");
QImage绘图设备
案例一:
![QImage像素设备](image/QImage像素设备.png)QImage img(300,300,QImage::Format_RGB32);
img.fill(Qt::white);
QPainter painter(&img);
painter.setPen(QPen(Qt::blue));
painter.drawEllipse(QPoint(150,150),100,100);
//保存
img.save("D:\\img.png");
案例二:
void Widget::paintEvent(QPaintEvent * )
{
QPainter painter(this);
//利用QImage 对像素进行修改
QImage img;
img.load(":/Image/Luffy.png");
// 修改像素
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
记录指令,随时加载。
保密效果。
//绘图设备
QPicture pic;
QPainter painter;
painter.begin(&pic);//开始往pic上面画
painter.setPen(QPen(Qt::cyan));
painter.drawEllipse(QPoint(150,150),100,100);
painter.end();//结束画画
//保存到磁盘
pic.save("D:\\pic.zt");
void Widget::paintEvent(QPaintEvent * )
{
QPainter painter(this);
//重现QPicture的绘图指令
QPicture pic;
pic.load("D:\\pic.zt");
painter.drawPicture(0,0,pic);
}
知识点十七、读写操作
QFile 文件读写操作
头文件:
#include<QFileDialog>//打开文件选取对话框
#include<QFile>//读写操作
#include<QTextCodec>//转码操作
打开文件
QString path = QFileDialog::getOpenFileName(this,"打开文件","D:\\my_code\\vsc\\QT\\05_Qt_QFile");
//将路径放入到lineEdit中
ui->lineEdit->setText(path);
//编码格式
//QTextCodec * codec = QTextCodec::codecForName("gbk");
//读取内容 放入到 textEdit中
// QFile默认支持的格式utf-8
QFile file(path);//参数就是读取文件的路径
读操作
该代码只能读UTF-8或GNK格式
改进:先判断在转换
//进行读操作
//设置打开方式
file.open(QIODevice::ReadOnly);
//QByteAraay array = file.readAll();
QByteArray array;
while(!file.atEnd())
{
array += file.readLine();//按行读
}
//将读取到的数据放入到textEdit中
ui->textEdit->setText(array);
//ui->textEdit->setText(codec->toUnicode(array));//编码格式对内容进行转码
//将文件对象进行关闭
file.close();
写操作
…
//进行写文件
file.open(QIODevice::Append);//用追加方式进行写
file.write("啊啊啊!");
file.close();
QFileInfo文件信息读取(其他信息)
文件大小 日期等信息
#include<QFontInfo>
#include<QDebug>
#include<QDateTime>
//QFileInfo 文件信息类
QFileInfo info(path);
qDebug() << "大小" << info.size() << "后缀名: " << info.suffix() << "文件名称: " << info.fileName() << " 文件路径: " << info.filePath();
//info.created(); 返回QDateTime 数据类型
//qDebug() << "创建日期: " << info.birthTime();
qDebug() << "创建日期: " << info.birthTime().toString("yyyy/MM/dd hh:mm:ss");