Qt网络编程笔记
原创
©著作权归作者所有:来自51CTO博客作者开始喜欢风的原创作品,请联系作者获取转载授权,否则将追究法律责任
本博客是在已经写完的一本笔记上而进行的,所以整理清除,结构清晰,有不懂的朋友可以一起交流呀。
下文为了方便,将(xxx.h)和(xxx.cpp)文件放到了一个代码区,以"空格+换行符+//"为分割线
初始代码(main.cpp)
因为main.cpp代码基本一样,因此在下文中该代码区的代码以此为准,如若修改会做说明
#include "mywidget.h"
#include <QApplication> // 应用程序类
#include <QWidget> // 窗口基类:一个大窗口
/*
QApplication应用程序类
Qt头文件my.h
头文件和类名一样
*/
int main(int argc, char *argv[])
{
// 有且只有一个应用程序类的对象
QApplication a(argc, argv);
// MyWidget继承于QWidget,QWidget是一个窗口基类
// 所以MyWidget也是窗口类
// w就是一个窗口
MyWidget w;
// 窗口创建默认是隐藏的,需要人为显示
w.show();
// 让程序一直执行,等待用户操作
return a.exec();
}
(基础 + 代码)部件部分
小贴士(small tips):指定父类(基类)的两种方式
// .cpp
#include <QPushButton>
// 1. setParent关键字
QPushButton b;
b.setParent(&w);
// 2. 通过构造参数传参
QPushButton b(&w);
小贴士(small tips):定义成员变量的两种方式
#include <QPushButton>
// 1. 普通创建(容易造成内存泄漏)
// .h
private:
QPushButton b;
// .cpp
b.setParent(this); // 指定父类
// 2. 通过指针创建
// .h
private:
QPushButton *b;
// .cpp
b2 = new QPushButton(this); // 指定父类
标准信号和槽
信号:由发出者发出的信息
槽:由接收者接收的信息
// mainwidget.h
#include <QPushButton>
private:
QPushButton b; // 定义一个成员对象
// mainwidget.cpp
#include "mainwidget.h"
#include <QPushButton>
#include <QMainWidget> // 主页面的基类,没有Widget类功能多,但是更精
MainWidget::MainWidget(QWidget *parent)
: QWidget(parent)
{
b.setParent(this);
b.setText("沙雕");
b.move(100, 100);
// 信号与槽举例
connect(&b, &QPushButton::pressed, this, &MainWidget::close);
/*
* &b:信号发出者
* &QPushButton::pressed:处理的信号
* this:信号接收者
* &MainWidget::close:槽函数,信号处理函数
*/
MainWidget::~MainWidget() // 析构函数
{
}
}
自 定义槽
// .h
void mySlot() // 声明槽函数
{
}
// .cpp
connect(&b2, &QPushButton::released, this, &MainWidget::mySlot);
void MainWidget::mySlot()
{
b.setText("123"); // 改变b按钮的显示文本
}
自定义信号
小贴士(small tips):创建两个窗口(A,B)并把他们联系起来+自定义信号
conclusion:当父窗口切换到子窗口的时候,直接切换;当子窗口切换到父窗口的时候,因为子窗口是在父窗口之中,因此子窗口必须先发射一个信号,这个信号是由子窗口按钮发出的。
// 第一步:分别创建两个窗口和两个按钮
// A.h
#include <QPushButton> // 给父窗口创建一个按钮用来切换页面
QPushButton b1;
// B.h
#include <QPushButton> // 给子窗口创建一个按钮用来切换页面
QPushButton b2;
// 第二步:把B作为A的子类
// A.h
#include "B.h" // 把子窗口头文件放到父窗口头文件里面
B b; // 创建一个子窗口的类
// 第三步:当是父类窗口的时候,点击按钮,会切换到子类窗口
// A.h
void change_windows(); // 改变窗口的函数
// A.cpp
#include <QPushButton>
connect(&b1, &QPushButton::release, this, &A::change_windows) // 建立一个槽函数
void B::change_windows()
{
this->hide(); // 父窗口隐藏
b.show(); // 子窗口显示
}
// 第四步:当是子类窗口的时候,点击按钮,会切换到父类窗口
// B.h
signals:
void mySiganl();
public:
void sendslots();
// B.cpp
#include <QPushButton>
connect(&b2, &QPushButton::clicked, this, &B::sendslots); // 自定义信号
void B::sendslots()
{
emit mySignal() // 发出信号
}
// A.h
void dealB(); // 父类中的槽函数
// A.cpp
connect(&b, &B::mySignal, this, A::deals); // b表示的是一个窗口,而不是一个按钮
void A::deals()
{
b.hide(); // 子窗口隐藏
this->show(); // 父窗口显示
}
信号二义性
illusion:当出现两个信号的时候,必须在父类中指定接收哪一个信号,不同的信号是由不同的动作发出来的
小贴士(small tips):信号出现重载
// B.cpp
#include <QPushButton>
connect(&b2, &QPushButton::clicked, this, &B::sendslots); // 自定义信号
void B::sendslots()
{
emit mySignal(250, "浩浩牛啊!")
}
// A.cpp
connect(&b, &B::mySignal, this, A::deals);
void A::deals(int a, Qstring str) // 接收信号的时候也要带上参数
{
b.hide(); // 子窗口隐藏
this->show(); // 父窗口显示
}
信号选择性
// 第一种方法:以函数指针代替信号
void (B::*sendslots1)() == &B::mySignal; // 声明这个信号(函数)是没有参数的
connect(&b, &B::sendslots1, this, A::deals);
void (B::*sendslots2)(int QString) == &B::mySignal; // 声明这个信号(函数)是有参数的
connect(&b, &B::sendslots2, this, A::deals);
void A::deals(int a, Qstring str) // 表明调用的是有参数的信号
{
b.hide(); // 子窗口隐藏
this->show(); // 父窗口显示
}
// 第二种方法:Qt4信号连接(容易出问题)
// Qt4槽函数必须有slots关键字来修饰
// A.h 中所有槽函数的声明都必须加上public slots
public slots:
void deal();
connect(&b, SIGNAL(mysignal()), this, SLOT(deal())); // 不带参数的信号和槽函数
connect(&b, SIGNAL(mysignal(int, QString)), this, SLOT(deal(int, QString))); // 带参数的信号和槽函数
lambda表达式之信号
// .cpp
// 变量传入只可读
#include <QPushButton>
#include <QDebug>
connect(&b, &QPushButton::checked,
[=]() // =以值传递传入外部所有的变量(可读),()表示函数的参数是匿名的
{
qDebug() << "你才是个猪头!";
}
)
// 变量传入只可读可改
#include <QPushButton>
#include <QDebug>
connect(&b, &QPushButton::checked,
[=]() mutable // =以值传递传入外部所有的变量(可读可改),()表示函数的参数是匿名的
{
qDebug() << "你才是个猪头!";
}
)
// 对于信号中有参数的情况
#include <QPushButton>
#include <QDebug>
connect(&b, &QPushButton::checked,
[=](bool isCheck) // bool isCheck指的是传入的参数
{
qDebug() << isCheck;
}
)
坐标系统
{
/*对于父窗口(主窗口,坐标系统相对于屏幕
* 原点:相对于屏幕左上角
* x:往右递增
* y:往下递增
*/
move(100, 100);
/*对于父窗口(主窗口,坐标系统相对于父窗口
* 原点:相对于窗口空白左上角(不包括边框)
* x:往右递增
* y:往下递增
*/
b1 -> resize(100, 100);
//设置按钮大小
}
(基础+代码)控件部分
菜单栏和工具栏
// 基类选择QMainWindow
#include "mainwindow.h"
#include <QMenuBar> // 菜单栏
#include <QMenu>
#include <QAction>
#include <QDebug>
#include <QToolBar> // 添加工具栏
#include <QPushButton> // 按钮
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
{
// 菜单栏
QMenuBar *mBar = menuBar(); // 构造参数构建菜单栏
// 添加菜单
QMenu *pFile = mBar->addMenu("文件"); // 添加小菜单
// 添加菜单项,添加动作
QAction *pNew = pFile->addAction("new"); // 每个小菜单里面的部件
connect(pNew, &QAction::triggered,
[=]()
{
qDebug() << "新建被按下";
}
);
pFile->addSeparator(); // 添加分割线
QAction *pOpen = pFile->addAction("open");
// 工具栏,菜单项的快捷方式
QToolBar *toolbar = addToolBar("toolbar");
// 工具栏添加快捷键
toolbar->addAction(pNew); // pNew表示的是菜单项对应的工具项,并且槽函数也是使用的是菜单项的槽函数
QPushButton *b = new QPushButton(this);
b->setText("^>^");
// 添加小控件
toolbar->addWidget(b); // 把工具项绑定按钮
// 信号处理
connect(b, QPushButton::clicked,
[=]()
{
b->setText("*——*");
}
);
}
MainWindow::~MainWindow() // 析构函数
{
}
状态栏
#include <QStatusBar> // 状态栏
#include <QLabel> // 标签
...
// 状态栏,左下角的状态
QStatusBar *sbar = statusBar();
QLabel *lable = new QLabel(this);
lable->setText("Normal text file");
// 添加小空间
sbar->addWidget(lable);
// 第二种添加方法,默认从左往右依次添加
sbar->addWidget(new QLabel("2", this));
// 第三种添加方法,默认从右往左依次添加
sbar->addPermanentWidget(new QLabel("2", this));
...
核心控件和浮动窗口
#include <QTextEdit> // 使用文本编辑区,
#include <QDockWidget> // 浮动窗口
// 核心控件
QTextEdit *Te = new QTextEdit(this); // 也可看做是一个小插件
this->setCentralWidget(Te);
// 浮动窗口
QDockWidget *dock = new QDockWidget(this);
this->addDockWidget(Qt::RightDockWidgetArea, dock); // 第一个参数是浮窗的初始位置
QTextEdit *Te2 = new QTextEdit(this); // 也可看做是一个小插件
dock->setWidget(Te2);
模态和非模态对话框
#include "mainwindow.h"
#include <QMenu>
#include <QMenuBar>
#include <QAction>
#include <QDialog>
#include <QDebug>
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
{
QMenuBar *mbar = menuBar();
setMenuBar(mbar);
QMenu *menu = mbar->addMenu("对话框");
QAction *p1 = menu->addAction("模态对话框");
connect(p1, &QAction::triggered,
[=]()
{
QDialog dlg;
dlg.exec() // 等待用户操作
qDebug() << "浩浩牛啊!";
}
);
QAction *p2 = menu->addAction("非模态对话框");
connect(p2, &QAction::triggered,
[=]()
{
QDialog *p = new QDialog;
p->setAttribute(Qt::WA_DeleteOnClose); // 关闭的时候才释放内存
p->show();
}
);
}
MainWindow::~MainWindow()
{
}
标准对话框和文件对话框
#include "mainwindow.h"
#include <QMenu>
#include <QMenuBar>
#include <QAction>
#include <QDialog>
#include <QDebug>
#include <QMessageBox> // 对话框
#include <QFileDialog> // 文件对话框
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
{
QMenuBar *mbar = menuBar();
this->setMenuBar(mbar);
QMenu *menu = mbar->addMenu("对话框");
QAction *p1 = menu->addAction("模态对话框");
connect(p1, &QAction::triggered,
[=]()
{
QDialog dlg;
dlg.exec() // 等待用户操作
qDebug() << "浩浩牛啊!";
}
);
QAction *p2 = menu->addAction("非模态对话框");
connect(p2, &QAction::triggered,
[=]()
{
QDialog *p = new QDialog;
p->setAttribute(Qt::WA_DeleteOnClose); // 关闭的时候才释放内存
p->show();
}
);
QAction *p3 = menu->addAction("关于对话框");
connect(p3, &QAction::triggered,
[=]()
{
QMessageBox::about(this, "about", "content"); // about是对话框的标题,content是内容
}
);
QAction *p4 = menu->addAction("问题对话框");
connect(p4, &QAction::triggered,
[=]()
{
int ret = QMessageBox::question(this,
"question", "content"
QMessageBox::Yes |
QMessageBox::Cancel // 指定类型
); // 默认给ok和no按钮
switch(ret)
{
case QMessageBox::Yes:
QDebug << "i am ok";
break;
case QMessageBox::No:
QDebug << "i am bad";
break;
default:
break;
}
}
);
// 文件对话框
QAction *p5 = menu->addAction("文件对话框");
connect(p5, &QAction::triggered,
[=]()
{
QString path = QFileDialog::getOpenFileName(
this, // 指定父对象
"open", // 显示操作
"../", // 显示路径
"source(*.cpp *.h);;Text(*txt);;all(*.*)" // 指定文件格式
);
QDebug() << path;
}
);
}
MainWindow::~MainWindow()
{
}
(进阶+UI)控件大全
如果要找到对应的控件,只需ui->xxx即可
Buttons:按钮类
特点:可以自动生成槽函数(右键,转向槽)
类型
| 作用
|
Push Button
| 按钮
|
Tool Button
| 按钮
|
Radio Button
| 单选按钮
|
Check Box
| 多选按钮
|
Command Link Button
| 控制链接按钮
|
Dialog Button Box
| ok、cancel
|
Containers:容器类
类型
| 作用
|
Group Box
| 放大部件容器
|
Scroll Area
| 可滑动
|
Tool Box
| 抽屉式容器
|
Tab Widgets
| 标签式容器
|
Stacked Widget
| 栈容器(可切换页面容器)
|
Frame
| 带边框的,布局容器
|
Widget
| 不带边框的,布局容器
|
MDI Area
| 文档分栏显示
|
Dock Widget
| 浮动窗口
|
QAxWidget
| 、、、
|
Input Widgets:输入类
类型
| 作用
|
Combo Box
| 下拉自定义选择框
|
Font Combo Box
| 字体选怎框
|
Line Edit(获取内容—text())
| 行编辑
|
Text Edit
| 文本编辑
|
Plain Text Edit
| 空白文本编辑
|
Spin Box
| 滑动调整数值(整数)
|
Double Spin Box
| 滑动调整数值(小数)
|
Time Edit
| 时间编辑器
|
Date Edit
| 日期编辑器
|
Date/Time Edit
| 时间/日期编辑器
|
Dial
| 控制器
|
Horizontal Scroll Bar
| 横向滚动条
|
Vertical Scroll Bar
| 纵向滚动条
|
Horizontal Slider
| 横向滑块
|
Vertical Slider
| 纵向滑块
|
Key Sequence Edit
| 设置快捷方式
|
小贴士(small tips):对于Line Edit(行编辑)
// 获取编辑框内容
Qstring text();
// 设置编辑框内容
setText();
// 设置显示间隙
setTextMargins(x, y, z, s) // 四个参数分别为距离左上右下的间距
// 设置显示模式
#include <QLineEdit>
setEchoMode(QLineEdit::Normal) 正常显示
setEchoMode(QLineEdit::NoEcho) 不显示任何内容
setEchoMode(QLineEdit::Password) 密码模式
setEchoMode(QLineEdit::PasswordEchoOnEdit) 编辑时显示字符否则为密码模式
Display Widgets:显示类
类型
| 作用
| 类型
| 作用
|
Label
| 设置标签
| Horizontal Line
| 横线
|
Text Browser
| 文本显示器
| Vertical Line
| 垂直线
|
Graphics View
| 绘图工具
| OpenGL Widget
| 此部分不做讲解
|
Calendar Widget
| 日历
| QDeclarative View
| 此部分不做讲解
|
LCD Number
| 数码管
| QQuickWidget
| 此部分不做讲解
|
Progress Bar
| 进度条
| QWebView
| 此部分不做讲解
|
小贴士(small tips):对于Label类
#include <QLabel>
// 设置文本内容
ui->labelText->setText("xxxx");
#include <QPixmap>
// 设置图片
ui->labelImage->setPixmap(QPixmap("workspace"));
// 让图片自动适应label大小
ui->labelImage->setScaledContents(true);
// 创建动画
#include <QMovie>
QMovie *myMovie = new QMovie("路径");
// 设置动画
ui->labelImage->setMovie(myMovie);
// 启动动画
myMovie->start();
ui->labelImage->setScaledContents(true);
// 设置html
ui->labelUrl->setText("<h1><a href=\"xxx\">xxx</a></h1>");
ui->labelUrl->setOpenExternalLinks(true);
小贴士(small tips):对于Progress Bar类
ui->progressBar->setMinimum(0); // 设置最小值
ui->progressBar->setMaximum(0); // 设置最大值
ui->progressBar->setValue(0); // 设置当前值
Spacer:弹簧类
类型
| 作用
|
Horizontal Spacer
| 横向弹簧
|
Vertical Spacer
| 纵向弹簧
|
Layouts:布局类
类型
| 作用
|
Vertical Layouts
| 纵向布局
|
Horizontal Layouts
| 横向布局
|
Grid Layouts
| 网格布局
|
Form Layouts
| 表格布局
|
自定义控件
把两个cpp文件相连接:【提升为】
Qt样式表
selector { attribute: value; },一般selectior为setStyleSheet()
/* such as
* 1. QLabel{ color: red} 第一种使用基本的颜色单词 默认设置的是字体的颜色
* 2. QLabel{ color: sgb(0, 255, 255)} 第二种使用RGB颜色配色
* 3. background-color:sgb(0, 0, 255) 背景色
* 4. background-image:url() 图片
*/
方箱重合
创建可伸缩样式
// 以按钮为例,对于按钮内的图片边框地带距离border距离要有4个像素点
QPushButton
{
border-width:4px;
border-image:url()
}
伪状态
QPushButton::press
{
border-image:url()
}
伪状态列表
伪状态
| 描述
| 伪状态
| 描述
|
::checked
| button部件被选中
| ::indeterminate
| checkbox或radiobutton被部分选中
|
::disabled
| 部件被禁用
| ::off
| 部件可以切换,且处于off状态
|
::enabled
| 部件被启用
| ::on
| 部件可以切换,且处于on状态
|
::focus
| 部件获得焦点
| ::pressed
| 部件被鼠标按下
|
::hover
| 鼠标位于部件上
| ::unchecked
| button部件未被选中
|
注明:写出来作用不大,主要是要自己会使用
事件
具体可见上一篇博客:
键盘和鼠标事件监听
QT中所有的事件类都继承于QEvent.
#include <QMouseEvent>
void mousePressEvent(QMouseEvent *ev) {}; // 鼠标按下
void mouseReleaseEvent(QMouseEvent *ev) {}; // 鼠标抬起
void mouseMoveEvent(QMouseEvent *ev) {}; // 鼠标移动
void enterEvent(QEvent *e); // 进入窗口区域
void leaveEvent(QEvent *e); // 离开窗口区域
void keyPressEvent(QKeyEvent *e) // 键盘按下事件
ev->button() == ???
事件的接收和忽略
ignore(); // 忽略事件,传递给父组件,不是父类
accept(); //接收事件
event()函数
控制各个函数的进程
#include <QEvent>
// 第一步:在主类头文件里面建立成员函数bool event(xxx)
// 第二步:定义函数来进行事件分发
// 第三步:代码
switch(e->type())
{
case QEvent::Close:
closeEvent(); // closeEvent此函数要自定义
.... // 如果传入的事件已被识别并且处理,则需要返回true,否则返回false,如果直接return true则可以跳过这个事件
}
事件过滤器:bool eventFitler
// 给控件安装过滤器
ui->label->installEventFilter(this); // this 表示是父对象
ui->label->setMouseTrack(); // 鼠标追踪
if(obj == label)
{
// 判断事件
if(e->type() == QEvent:: MouseMove)
{
ui->label->setTEext("sadf");
return true; // 不要让事件传播
}
}
(进阶+代码)其他工具
绘图
文件操作
网络通信
TCP
UDP
线程