QT用来做用户界面的,主要做 PC上的用户界面。
用户界面---UI (User Interface)
特点: 1.跨平台 win linux macos ......
2.开源: 非盈利型的免费 商业:收费
3.面向对象的,使用C++开发[ qt改进了C++], 执行效率高
4.qt提供了全套方法: UI 进程 线程 文件 数据 网络 .......
大纲:
UI设计: 各种控件 控件之间的通信
进程 线程 文件 数据 网络
1、信号和槽:是qt特有的方式,标准C++是无法完成这种功能,qt改进了C++.
信号signal: 对象因为某种事件,发出信号。
槽slot: 信号的接收者,处理信号的对象,接受者收到信号之后,使用槽函数来处理信号。
一个信号可以发送给多个接收者;一个接收者可以接收多种信号。
用于对象之间的通信:一个对象发出信号,另一个对象接受信号并处理信号。
2、控件:控制的小部件,按钮 文本框 label 单选 复选 ....
分为两类: (1)文本框 按钮 单选 复选 .....
(2)对话框
父对象: 和继承没有关系,比如btn对象,想显示在 背景对象之上,btn对象要把parent对象设置为 背景对象.
qt会按照这套规则, 让子对象显示在父对象之上,qt在显示父对象的时候,也同时会显示 父对象的所有子对象。
控件继承关系:
所有的小控件,都继承自 QWidget,它实现了背景
qt所有的类,都继承自 QOBject类,这是一个 qt的基础类,,内部实现了对象树(父对象 子对象), 信号和槽
2.1按钮: QPushButton
信号
clicked() 信号---- 鼠标弹起的时候触发信号
pressed()信号---- 鼠标按下的时候触发信号
release() 信号---- 鼠标释放的的时候,和clicked()一样
显示:
setText(QString txt);
setEnabled(bool show);
2.2标签 QLabel
显示文本/图片,使用者不能修改内容
显示:设置文本内容 setText(QString name)
.setWordWrap(bool) 是否换行显示
获取 QString text();
显示图片: 不允许text和image同时显示
qt首先创建资源管理器,把图片加入该资源resource. 每张图像都有一个内部路径
前提:建议在本地文件夹下创建rs目录,里面放上需要的图片 (Label目前只支持PNG图像)
1.创建资源resource
2.编译出效果 ctrl+B /左下角-那个锤子
.setPixmap(QPixmap &pix) 给label设定要显示的图像
.setScaledContents(bool ); 是否允许内容缩放
2.3输入框 QLineEdit-行输入框 QTextEdit--多行输入
QLineEdit:
信号:
editingFinish() 当用户正在编辑,突然回车或者用户鼠标点击其他地方(失去焦点),表示输入完毕。
textChanged(QString &) 只要文本改变就触发信号(每改变一个字符,就触发该信号),参数表示当前文本框的全部内容。
显示:
显示有两种方式:一种是明文显示(默认),一种是密文显示
.setEchoMode( QLineEdit::Normal /QLineEdit:: Password );
代码中获取用户输入 QString .text();
设置显示内容 .setText(QString )
QTextEdit: 多行输入
显示:
设置文本 setText(QString );
获取文本: QString toPlanText();
清空文本: .clear()
追加文本: append(QString txt)
2.4单选 和多选
多选: QCheckBox
信号:stateChanged(int sel) 当某个多选按钮改变,发出该信号,信号中包含了当前的状态(被选中-2 未选中-0)。
显示: setText(QString);
判断是否被选中: bool isChecked();
设置状态(被选中-未被选中) : setChecked(bool)
单选框:QRadioButton
信号:clicked() 当你点击某个对象的时候,该对象发出这个信号
显示:setText(QString)
判断是否被选中 bool isChecked();
设置选中/未选中 setChecked(bool )
2.5分组框:QGroupBox
设置标题 setTitle(QString)
2.6组合框/下拉框 QComboBox
构成 QComboBox 整个下拉框
添加主题 addItem(QString itemName )
item的个数 int .count();
删除主题 removeItem(int pos)
信号: 当用户选择某个主题,发出信号
currentIndexChanged(const QString &txt)
Item index和Item string的转换
int findText(QString) 根据item的字符串找到 位置pos
QString itemText(int index)
获取当前选择的项/主题
int currentIndex(); 当前选得是第几个
QString currentText(); 当前选择的 item的文本
QComboBoxItem 每一项/主题
2.7QSpinBox-int QDoubleSpinBox-double类型 微调框
QSpinBox/QDoubleSpinBox:
程序获取用户输入 T .value();
程序设置值 .setValue(T val)
设置最大值/最小值: setMaximum(T val) setMinimum(T val)
信号:当输入改变,给出一个信号 valueChanged(T val )
前缀和后缀: setPrefix(QString ) setSuffix(QString)
2.8QSlider 滑动输入
信号:valueChanged(int ) 当你拖动的时候,发出信号,包含当前的值
设置:最大值 setMaximum (int val) 最小值 setMinimum(int val);设置默认值setValue(int) 获取当前值int value()
2.9QProgressBar 进度条,用户不可以改动
setValue(int val)
int value();
setMaximum(int val) setMinimum(int val)
设置方向的:setOrientation( Qt::Vertical / Qt::Horizontal )
2.10、对话框 QDialog
消息对话框 QMessageBox
又分为几种 静态函数 about() information() critical() question() warning()
文件对话框 QFileDialog
静态函数 getOpenFileName getSaveFileName getExistingDirectory 打开对话框-选择打开文件 指定文件保存的名字 指定目录
输入对话框
字体 QFont ,描述了字体的各种属性、颜色QColorDialog : QColor qt的颜色类,内部有RGB三色值。
3、布局 layout
问题:各种控件排放很乱,也没有对齐
放屏幕分辨率变化的时候,内部的控件没变
布局可以解决上述问题,注意 不敢分辨率如何变化,长宽比不要变(16:9)。
基本布局,只有两种 :
QVLayoutBox--垂直布局 内部的控件都是垂直摆放
QHLayoutBox-水平布局 内部控件都是水平摆放
我们常见的都是 两者的混合, 嵌套布局
如果布局不能满足要求:
1.margin 边距(左 右 上 下) + 间距(控件间距)
2.弹簧,他们是不可显示的控件,但是也占空间
3.布局可以 设定内部控件的比例
4、菜单 Qmenu
菜单栏-- QMenuBar
内有很多菜单 QMenu
菜单中有很多项 菜单项- QAction
创建工程:
这一次 class base选择 QMainWindow, 以前QWidget,只是增加了菜单栏
QMenuBar QMenu 他们只是菜单项的组织形式,他们不干活.
每个QAction菜单项都有一个信号,当你单击它的时候发出信号,QAction::triggered()
5、绘图:
画家(QPainter-知道如何作画)使用作案工具( 画笔QPen 画刷QBrush)在设备(窗体Widget)上 绘画,QPainter可以绘制点 线 矩形 多边形 园 椭圆 弧形 文字 图片 ....
画笔QPen 用来画外线。OPen pen; pen.setColor( QColor color; ); QColor color(R,G,B);pen.setWidth(int width); 单位是像素点
pen.setStyle( Qt::SolidLine/Qt::DashLine /.... )
画刷QBrush 用来填充的
QBrush brush; brush.setColor( QColor color; ); QColor color(R,G,B);
brush.setStyle( Qt::SolidPattern /Qt::Dense1Pattern/ )
画家QPainter p(父对象);
p.setPen(pen/Qt::NoPen); p.setBrush(brush/Qt::NoBrush);
p.drawPix()
p.drawLine()
p.drawRect()
p.drawFont p.drawPic
Qt中文件的操作
面向对象的 文件对象QFile
QFile-->QFileDevice-->QIODevice-->QOBject类
QFile filename(QString filename); 创建对象并绑定
打开 bool filename.open(QIODevice::ReadOnly ) //QIODevice::ReadOnly/QIODevice::WriteOnly/
QIODevice::ReadWrite/QIODevice::Append/QIODevice::Truncate
读取: int read(char *buf, int bufsize);返回值:正值---实际读取的大小,0-结尾了,负值--出错了。
写入: int file.write(char *wbuf,int wsize); 将wbuf中的内容写入文件,长度wsize,返回值: 正值---实际写入大小,负数:err
关闭 file.close();
创建: open 然后close 一个不存在的文件,恭喜你可以啦
删除文件: file.remove();
文件信息
QFileInfo fileinfo(filename); //执行构造函数,对象内部已经获取了文件所有信息
QString fileinfo.filePath()--路径; QString fileinfo.fileName() --名字;
bool fileinfo.isDir(); 判断是目录吗
bool fileinfo.isFile()--判断是普通文件吗; bool fileinfo.isSymLink()是否是连接;
int fileinfo.size(); 文件大小
QT线程
我们知道主线程(又称 GUI线程),负责监控窗口上的任何事件,一旦发现事件,立马处理。但是有时候,任务很耗时,GUI进程会卡住,UI无响应
创建一个新的子线程,负责处理 耗时的任务,###GUI线程只负责 UI刷新####.
注意事项:非GUI线程禁止访问 界面上任何元素;
如果非要显示,子线程要传递数据给GUI,有GUI线程负责刷新。
如何创建线程:
C语言: pthread_create(thread_fun) thread_fun() {while(1){ }}
Qt提供了 QThread 类, 实现了线程功能,其中有一个方法 virtual void run() ;就是线程执行体。
实现一个QThread子类 myThread,重写run函数即可.
1. new 子类对象
2. start(); 线程已经执行run了.
互斥锁QMutex:
我们直到,线程间 可以共享内存,于是他们之间就可以通信.
但是 如果两个线程同时访问同一个资源,就会出现问题, 解决方法---加锁
睡眠函数 静态方法QThread::msleep(int msec);
网络(Internet) 需要在 工程.pro中,添加 QT += network
qt提供了socket接口,但是这套接口 基于信号和槽的,而且qt所有的函数默认都是非阻塞的
qt网络主要用在 客户端,服务器主要用来写小型 测试的服务器。
客户端 服务器
fd=socket() listenfd=socket();
ret = connect(ip,port); bind(self_ip,port);
while(1){ lisetn();
sned(buf,len); while(1){
recv(buf,len); newfd=accept();
sleep(1); 加入集合或者线程....
} }
close(fd);
客户端 QTcpSocket提供实现
1. QTcpSocket *pCli = new QTcpSocket; 创建socket对象
信号: readyRead() 当socket发现服务器有数据发过来了,会发出该信号 pCli->read(rbuf,rlen);
connected() 当连接建立成功,socket发出该信号
disConnected() 当对方关闭,socket发出这个信号
2. pCli->connectToHost(serv_ip,port); 建立连接,非阻塞函数,无法知道连接成功与否
如何知道连接成功了..方法1:等信号 QTcpSocket会发出信号connected()给你
方法2: socket提供了阻塞等待连接的方法
bool QTcpSocket::waitForConnect(int msec)
3. ret = pCli->write(char *buf, int len); 非阻塞的
pCli->disConnectFromHost();
pCli->close();
服务器:
1.创建服务器socket对象 QTcpServer实现了主socket
QTcpServer *pServ=new QTcpServer;
建立newConnect信号的槽函数, 当servSocket发现有客户端连接的时候,就会发出该信号
2. 绑定和监听, 指定本地ip和port
QTcpServer::listen( serv_ip/0, serv_port );
3. 等信号,当客户端发起连接的时候, pServ 感知到客户端并发出 newConnect()信号
4.在 newConnect的槽函数里面:
获取客户端的新连接 ,获取客户端socket, QTcpSocket *pcli = pServ->获取最新的客户端socket;
建立信号: readyRead() disconnected()
后续则使用pcli和客户端通信.
发送 pcli->write(char *buf,int len);
接收数据: 等待信号 readyRead()
如何获取对方关闭: disconnected()信号
结构体对齐
struct data {
char aa;
short bb;
};
自然对齐: 变量存放的地址是其大小的整数倍,比如一个整数,那么他只能放在 0-4-8-12-16-....的位置。
struct data{
short aa;
char bb;
};
结构体对齐: 加快cpu访问速度
1.自然对齐
2.整个结构体大小必须是 机器字长(32bit 64bit)的整数倍
问题:
在同一台电脑上, 结构体的不同变量大小一致.
不同电脑上,比如 32bitcpu和64bitcpu,同一个结构体变量大小 可能不一样.
如何解决问题:
通信的结构体一般按照 紧凑布局,就是不要 对齐.
linux C语言:
struct data {
} __attribute__((packed)); linux特有的风格
QT:
#pragma pack(push)
#pragma pack(1) 取消对齐
struct {
};
#pragma pack(pop)