QT
QT概述
Qt是一个跨平台的C++图形用户界面应用程序框架。
QT下载用清华的镜像,速度快。
QT优点
- 跨平台
- 接口简单
- 简化了内存回收机制
- 开发效率高
- 有很好的社区氛围
- 可以进行嵌入式开发
创建项目
Qwidget为父类 QMainWindow QDialog为子类 QMainWindow比父类多菜单栏、状态栏 QDialog对话框
main.cpp
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| #include "mywidget.h" #include <QApplication>
int main(int argc, char *argv[]) { QApplication a(argc, argv); myWidget w; w.show(); return a.exec(); }
|
.por文件解释
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| QT += core gui
greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
TARGET = 01_project TEMPLATE = app
DEFINES += QT_DEPRECATED_WARNINGS
SOURCES += \ main.cpp \ mywidget.cpp
HEADERS += \ mywidget.h
|
.h头文件
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
| #ifndef MYWIDGET_H #define MYWIDGET_H
#include <QWidget>
class myWidget : public QWidget { Q_OBJECT
public: myWidget(QWidget *parent = 0); ~myWidget(); };
#endif
|
.cpp文件
1 2 3 4 5 6 7 8 9 10 11 12
| #include "mywidget.h"
myWidget::myWidget(QWidget *parent) : QWidget(parent) { }
myWidget::~myWidget() {
}
|
帮助文档
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| QPushButton Class The QPushButton widget provides a command button. More...
Header: #include <QPushButton>
qmake: QT += widgets
Inherits: QAbstractButton Inherited By: QCommandLinkButton
List of all members, including inherited members
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| QPushButton *btn=new QPushButton; btn->setParent(this); btn->setText("第一个按钮"); btn->resize(50,50); QPushButton *btn1=new QPushButton("第二个按钮",this); btn1->move(100,0); resize(600,400); setFixedSize(600,400); setWindowTitle("第一个窗口");
|
对象树
概念
当常见的对象再堆区时,如果指定的父亲是QObject派生下来的类或者QObject的子类派剩下来的类,可以不用管理释放的操作,将对象放入对象树中
例子:new Teacher(this)
窗口不能再放入窗口的对象树中
作用
一定程度上简化了回收机制
综上所述 在QT中创建对象时就指定父类对象
坐标系
左上角为(0,0)X向右 y向下
信号和槽
connect(信号发送者,发送的信号(函数地址 siginal),信号接收者,信号处理(槽 slot 函数的地址,信号的地址)) 第五个参数多线程时才有意义,默认使用队列 如果是单线程默认直接 队列槽函数所在的线程和接收者一样 直接 槽函数所在的线程和发送者一样
例子:
1
| connect(myBtn,&QPushButton::clicked,this,&myWidget::close);
|
信号槽的优点,松散耦合,信号发送端和接受段本身是没有关联的,通过connect连接将两端连接起来
自定义信号:
1 2 3 4 5
| signals: void hungry();
|
自定义槽:
1 2 3 4 5
| public slots: void treat();
|
自定义的连接
1 2 3 4 5 6
| this->zt=new Teacher(this); this->st=new Student(this);
classIsOver();
|
自定义触发
1 2 3
| void Widget::classIsOver(){ emit zt->hungry(); }
|
自定义的信号发送者,接收者 以及触发函数均需写在窗口类Widget的private中:
1 2 3 4 5
| private: Ui::Widget *ui; Teacher *zt; Student *st; void classIsOver();
|
重载时
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| void hungry(QString foodName); void Student::treat(QString foodName){ qDebug()<<"请老师吃"+foodName; }
void(Teacher::*teacherSignal)(QString)=&Teacher::hungry; void(Student::*studentSlot)(QString)=&Student::treat; connect(zt,teacherSignal,st,studentSlot); classIsOver();
void Widget::classIsOver(){ emit zt->hungry("宫保鸡丁"); }
|
信号连接信号
1 2 3 4
| void(Teacher::*teacherSignal)(void)=&Teacher::hungry; void(Student::*studentSlot)(void)=&Student::treat; connect(zt,teacherSignal,st,studentSlot); connect(btn,&QPushButton::clicked,zt,teacherSignal);
|
断开信号
1 2 3 4 5 6 7 8 9 10
| disconnect(zt,teacherSignal,st,studentSlot); 参数为 信号发送者,发送的信号(函数地址 siginal),信号接收者,信号处理(槽 slot 函数的地址,信号的地址) connect(btn,&QPushButton::clicked,this,[=](){ emit zt->hungry("宫爆鸡丁"); });
|
lambda表达式
MainWindow
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50
| QMenuBar *bar=menuBar(); setMenuBar(bar); QMenu * fileMenu=bar->addMenu("文件"); QMenu * editMenu=bar->addMenu("编辑");
QAction * newAction=fileMenu->addAction("新建"); fileMenu->addSeparator(); QAction * openAction=fileMenu->addAction("打开");
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 * stBar=statusBar(); setStatusBar(stBar); QLabel * lable=new QLabel("提示信息",this); stBar->addWidget(lable); QLabel * lable2=new QLabel("提示信息",this); stBar->addPermanentWidget(lable2);
QDockWidget * dockWidget=new QDockWidget("浮动",this); addDockWidget(Qt::BottomDockWidgetArea,dockWidget); dockWidget->setAllowedAreas(Qt::TopDockWidgetArea|Qt::BottomDockWidgetArea);
QTextEdit * edit=new QTextEdit(this); setCentralWidget(edit);
|
使用ui设计时十分方便,若要在代码中获得某个部件 可使用 ui->部件名字
添加资源文件
对话框
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| connect(ui->actionnew,&QAction::triggered,this,[=](){ QDialog *dlg=new QDialog(this); dlg->resize(200,100); dlg->exec(); qDebug()<<"模态框弹出来";
});
|
标准对话框 QMessageBox
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
|
QMessageBox::warning(this,"warning","警告"); });
|
其他对话框
1 2 3 4 5 6 7 8 9 10 11 12 13 14
|
bool flag; QFont q=QFontDialog::getFont(&flag,QFont("华文彩云",36)); qDebug()<<q;
|
页面布局
利用布局方式,给窗口进行美化
选取widget 进行布局 水平 垂直 栅格
默认窗口和控件之间有9间隙 ,选中窗口在 layout margin中调整
内部的间隙可以用弹簧分割 horizontal space
窗口默认特别大在sizePolicy中垂直策略改为fixed
文本款格式在echoMode中设置 需要密码框则选择为password
控件
按钮组
- QPushButton 常用按钮
- QToolButton 工具按钮用于显示 图片,如果想显示文字,修改风格 toolButtonStyle 凸起的风格 autoRaise
- radiaButton 单选按钮,设置默认 setchecked
- checkbox 多选按钮,2是选中 1是半选中 0是未选 状态代码
1 2 3
| connect(ui->checkBox,&QCheckBox::stateChanged,this,[=](int state){ qDebug()<<state; });
|
列表容器
QListWidget列表容器
1 2 3 4 5 6 7 8
|
QStringList list; list<<"锄禾日当午"<<"汗滴禾下锄"; ui->listWidget->addItems(list);
|
树控件
QTreeWidget 树控件
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| ui->treeWidget->setHeaderLabels(QStringList()<<"英雄"<<"英雄介绍"); QTreeWidgetItem * item=new QTreeWidgetItem(QStringList()<<"力量"); QTreeWidgetItem * item1=new QTreeWidgetItem(QStringList()<<"敏捷"); QTreeWidgetItem * item2=new QTreeWidgetItem(QStringList()<<"智力"); ui->treeWidget->addTopLevelItem(item); ui->treeWidget->addTopLevelItem(item1); ui->treeWidget->addTopLevelItem(item2); QTreeWidgetItem * heroL1=new QTreeWidgetItem(QStringList()<<"刚被猪"<<"前排坦克,能在吸收伤害的同时造成客观的范围输出"); QTreeWidgetItem * heroL2=new QTreeWidgetItem(QStringList()<<"刚被猪"<<"前排坦克,能在吸收伤害的同时造成客观的范围输出"); item->addChild(heroL1); item1->addChild(heroL2); item2->addChild(heroL1);
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
|
ui->tableWidget->setColumnCount(3);
ui->tableWidget->setHorizontalHeaderLabels(QStringList()<<"姓名"<<"性别"<<"年龄");
ui->tableWidget->setRowCount(5); QStringList nameList=QStringList()<<"亚瑟"<<"1"<<"2"<<"3"<<"4"; QStringList sex=QStringList()<<"亚瑟"<<"1"<<"2"<<"3"<<"4"; 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(sex.at(i))); ui->tableWidget->setItem(i,col++,new QTableWidgetItem(QString::number(i))); }
|
其他控件
栈控件 stackedWidget
下拉框 comboBox
QLable 显示图片、动图
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
| connect(ui->btn_scrollArea,&QPushButton::clicked,this,[=](){ ui->stackedWidget->setCurrentIndex(0); }); connect(ui->btn_ToolBox,&QPushButton::clicked,this,[=](){ ui->stackedWidget->setCurrentIndex(1); }); connect(ui->btn_TabWidget,&QPushButton::clicked,this,[=](){ ui->stackedWidget->setCurrentIndex(2); });
ui->comboBox->addItem("奔驰"); ui->comboBox->addItem("宝马"); ui->comboBox->addItem("兰博基尼");
connect(ui->pushButton_6,&QPushButton::clicked,this,[=](){ ui->comboBox->setCurrentText("兰博基尼"); });
ui->label->setPixmap(QPixmap(":/image/la.jpg"));
|
自定义控件
- 添加新文件 ->Qt->设计师界面类(.h .cpp .ui)
- ui中设计QspinBox和QSlider 两个控件
- Widget 使用自定义控件 首先拖拽 Widget 控件 其次提升为 写入类名 全局包含 添加
- 信号和槽的监听 提供对外接口
- 在主控制中使用
占位符
1 2
| QString str=QString("鼠标点击了 x=%1 y=%2 ").arg(ev->x()).arg(ev->y()); %数字代表第几个arg的参数
|
事件 均需要在函数中进行重写
在ui中拖入后,提升为自己所写的类然后进行事件编辑
鼠标事件
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
| name::name(QWidget *parent) : QLabel(parent) { setMouseTracking(true); } void name::enterEvent(QEvent *event){ qDebug()<<"鼠标进入了"; } void name::leaveEvent(QEvent *event){ qDebug()<<"鼠标离开了"; } void name::mouseMoveEvent(QMouseEvent *ev){
qDebug()<<"鼠标移动了"; } void name::mousePressEvent(QMouseEvent *ev){ if(ev->button()==Qt::LeftButton){ QString str=QString("鼠标点击了 x=%1 y=%2 ").arg(ev->x()).arg(ev->y()); qDebug()<<str;} } void name::mouseReleaseEvent(QMouseEvent *ev){ qDebug()<<"鼠标松开了"; }
|
定时器1
利用时间timerevent
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWindow) { ui->setupUi(this); id1=startTimer(1000); id2=startTimer(2000); }
MainWindow::~MainWindow() { delete ui; } void MainWindow::timerEvent(QTimerEvent *event){ if(event->timerId()==id1){ static int num=1; ui->label_2->setText(QString::number(num++)); }else if(event->timerId()==id2){ static int num2=1; ui->label_3->setText(QString::number(num2++)); } }
|
1 2 3 4 5 6 7 8 9 10 11
| QTimer * timer=new QTimer(this); timer->start(500); connect(timer,&QTimer::timeout,this,[=](){ static int num=1; ui->label_4->setText(QString::number(num++)); }); connect(ui->pushButton,&QPushButton::clicked,this,[=](){ timer->stop(); });
|
event事件
用于事件分发,也可以做拦截操作,不建议
1 2 3 4 5 6 7 8 9 10 11 12 13
| bool name::event(QEvent *e){ if(e->type()==QEvent::MouseButtonPress){ QMouseEvent * ev= static_cast<QMouseEvent *>(e); QString str=QString("鼠标点击了 x=%1 y=%2 ").arg(ev->x()).arg(ev->y()); qDebug()<<str; return true; } return QLabel::event(e); }
|
事件过滤器
在事件分发前进行过滤
- 给控件安装事件过滤器
- 重写eventfilter事件
//安装事件过滤器
ui->label->installEventFilter(this);
//重写eventFilter事件
bool MainWindow::eventFilter(QObject *watched, QEvent *event){
if(watched==ui->label){
if(event->type()==QEvent::MouseButtonPress){
return true;
}
}
return QWidget::eventFilter(watched,event);
}
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51
| #### 绘图事件
```js void MainWindow::paintEvent(QPaintEvent *){ //实例化画家 QPainter *painter=new QPainter(this);//指明绘图设备 //设置画笔 QPen *pen=new QPen(QColor(0,255,0)); pen->setWidth(3); pen->setStyle(Qt::DotLine); painter->setPen(*pen); //设置画刷 QBrush *brush=new QBrush(QColor(0,0,255)); brush->setStyle(Qt::Dense7Pattern); painter->setBrush(*brush); //线 painter->drawLine(QPoint(0,0),QPoint(100,100)); //圆 painter->drawEllipse(QPoint(100,100),50,50); //矩形 painter->drawRect(QRect(QPoint(100,100),QPoint(200,200))); //字 painter->drawText(QRect(10,200,100,50),"好好学习"); ---------高级设置--------- 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)); //让画家移动100 painter.translate(100,0);
//保存画家状态 painter.save(); painter.drawRect(QRect(20,20,50,50)); //还原画家的状态 painter.restore(); painter.drawRect(QRect(20,20,50,50)); } //利用画家 画资源文件 QPainter painter(this); painter.drawPixmap(x,20,100,100,QPixmap(":/image/la.jpg")); //超过屏幕宽度就返回 if(x>this->width()){ x=0; }
|
绘图设备
Qpixmap QImage QBitmap(黑白色) Qpicture QWidget
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
| ui->setupUi(this);
QPicture pic; QPainter painter; painter.begin(&pic); painter.setBrush(QBrush(QColor(Qt::blue))); painter.drawEllipse(QPoint(50,50),50,50); painter.end(); pic.save("E:/pic.zt");
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| void MainWindow::paintEvent(QPaintEvent *event){ QPainter painter(this);
QPicture pic; pic.load("E:/pic.zt"); painter.drawPicture(0,0,pic); }
|
文件操作
文件读写
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| QFile file(s); file.open(QIODevice::ReadOnly); QByteArray array=file.readAll(); QByteArray a; while(!file.atEnd()){ a+=file.readLine(); } ui->textEdit->setText(array); file.close();
file.open(QIODevice::Append); file.write("111"); file.close();
|
文件信息读取
1 2 3 4
| QFileInfo info(s); qDebug()<<info.suffix();
|
网络通信
tcp
在pro文件中加入network 模块
服务器端
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97
| #ifndef WIDGET_H #define WIDGET_H
#include <QWidget> #include <QTcpServer> #include <QTcpSocket> namespace Ui { class Widget; }
class Widget : public QWidget { Q_OBJECT
public: explicit Widget(QWidget *parent = 0); ~Widget();
private slots: void on_btn_send_clicked();
void on_btn_close_clicked();
private: Ui::Widget *ui; QTcpServer *tcpServer; QTcpSocket *tcpSocket; };
#endif
#include "widget.h" #include "ui_widget.h"
Widget::Widget(QWidget *parent) : QWidget(parent), ui(new Ui::Widget) { ui->setupUi(this); tcpServer=NULL; tcpSocket=NULL; tcpServer=new QTcpServer(this); tcpServer->listen(QHostAddress::Any,8888); setWindowTitle("服务器8888"); connect(tcpServer,&QTcpServer::newConnection,this,[=](){ tcpSocket=tcpServer->nextPendingConnection(); QString ip=tcpSocket->peerAddress().toString(); qint16 port=tcpSocket->peerPort();
QString temp=QString("[%1:%2]:成功连接").arg(ip).arg(port); ui->text_read->setText(temp);
connect(tcpSocket,&QTcpSocket::readyRead,this,[=](){ QByteArray array=tcpSocket->readAll(); ui->text_read->append(array); }); });
}
Widget::~Widget() { delete ui; }
void Widget::on_btn_send_clicked() { if(NULL==tcpSocket){ return; } QString str=ui->text_write->toPlainText(); tcpSocket->write(str.toUtf8().data()); }
void Widget::on_btn_close_clicked() { if(NULL==tcpSocket){ return; } tcpSocket->disconnectFromHost(); tcpSocket->close(); tcpSocket=NULL; }
|
客户端
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86
| #ifndef CLIENTWIDGET_H #define CLIENTWIDGET_H
#include <QWidget> #include <QTcpSocket> namespace Ui { class ClientWidget; }
class ClientWidget : public QWidget { Q_OBJECT
public: explicit ClientWidget(QWidget *parent = 0); ~ClientWidget();
private slots: void on_connect_clicked();
void on_send_clicked();
void on_close_clicked();
private: Ui::ClientWidget *ui; QTcpSocket *tcpSocket; };
#endif
#include "clientwidget.h" #include "ui_clientwidget.h" #include <QHostAddress> ClientWidget::ClientWidget(QWidget *parent) : QWidget(parent), ui(new Ui::ClientWidget) { ui->setupUi(this); setWindowTitle("客户端"); tcpSocket=NULL; tcpSocket=new QTcpSocket(this); connect(tcpSocket,&QTcpSocket::connected,[=](){ ui->textEdit_read->setText("成功和服务器建立"); }); connect(tcpSocket,&QTcpSocket::readyRead,[=](){ QByteArray array=tcpSocket->readAll(); ui->textEdit_read->append(array); }); }
ClientWidget::~ClientWidget() { delete ui; }
void ClientWidget::on_connect_clicked() { if(NULL==tcpSocket){ return; } QString ip=ui->lineEdit_ip->text(); qint16 port=ui->lineEdit_port->text().toInt(); tcpSocket->connectToHost(QHostAddress(ip),port);
}
void ClientWidget::on_send_clicked() { if(NULL==tcpSocket){ return; } QString str=ui->textEdit_2->toPlainText(); tcpSocket->write(str.toUtf8().data()); }
void ClientWidget::on_close_clicked() { tcpSocket->disconnectFromHost(); tcpSocket->close(); }
|
udp
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42
| #include "widget.h" #include "ui_widget.h"
Widget::Widget(int i,QWidget *parent) : QWidget(parent), ui(new Ui::Widget) { ui->setupUi(this); udpSocket=new QUdpSocket(this); udpSocket->bind(i); setWindowTitle(QString("服务器端口为%1").arg(i)); connect(udpSocket,&QUdpSocket::readyRead,this,&Widget::dealMsg); }
Widget::~Widget() { delete ui; } void Widget::dealMsg(){ QHostAddress cliAddr; quint16 port; char buf[1024]={0}; qint64 len=udpSocket->readDatagram(buf,sizeof(buf),&cliAddr,&port); if(len>0){ QString str=QString("[%1:%2]%3").arg(cliAddr.toString()).arg(port).arg(buf); ui->textEdit->setText(str); } }
void Widget::on_btn_send_clicked() { QString ip=ui->lineEdit_ip->text(); qint16 port=ui->lineEdit_port->text().toInt(); QString str=ui->textEdit->toPlainText(); udpSocket->writeDatagram(str.toUtf8(),QHostAddress(ip),port); }
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
| #ifndef WIDGET_H #define WIDGET_H
#include <QWidget> #include <QUdpSocket> namespace Ui { class Widget; }
class Widget : public QWidget { Q_OBJECT
public: explicit Widget(int i=8888,QWidget *parent = 0); ~Widget(); void dealMsg(); private slots: void on_btn_send_clicked();
private: Ui::Widget *ui; QUdpSocket *udpSocket; };
#endif
|
组播
1 2 3 4 5 6 7 8 9 10
| udpSocket->bind(QHostAddress::AnyIPv4,i); udpSocket->joinMulticastGroup(QHostAddress("224.0.0.2")); setWindowTitle(QString("服务器端口为%1").arg(i)); connect(udpSocket,&QUdpSocket::readyRead,this,&Widget::dealMsg);
|
发文件
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100
| #include "mainwindow.h" #include "ui_mainwindow.h" #include <QFileDialog> #include <QDebug> #include <QFileInfo> MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWindow) { ui->setupUi(this); tcpServer=new QTcpServer(this); tcpServer->listen(QHostAddress::Any,8888); setWindowTitle("服务器端口为8888"); ui->btn_select->setEnabled(false); ui->btn_send->setEnabled(false); connect(tcpServer,&QTcpServer::newConnection,this,[=](){ tcpSocket=tcpServer->nextPendingConnection(); QString ip=tcpSocket->peerAddress().toString(); quint16 port=tcpSocket->peerPort(); QString str=QString("[%1:%2]成功连接").arg(ip).arg(port); ui->textEdit->setText(str); ui->btn_select->setEnabled(true); });
connect(&timer,&QTimer::timeout,this,[=](){ timer.stop(); sendData(); }); }
MainWindow::~MainWindow() { delete ui; }
void MainWindow::on_btn_select_clicked() { QString path=QFileDialog::getOpenFileName(this,"open","../"); if(false== path.isEmpty()){ fileName.clear(); fileSize=0; sendSize=0; QFileInfo info(path); fileName=info.fileName(); fileSize=info.size(); file.setFileName(path); bool isOk=file.open(QIODevice::ReadOnly); if(!isOk){ qDebug()<<"打开失败"; } ui->textEdit->append(path); ui->btn_select->setEnabled(false); ui->btn_send->setEnabled(true); }else{ qDebug()<<"选择文件路径出错"; } }
void MainWindow::on_btn_send_clicked() { QString head=QString("%1##%2").arg(fileName).arg(fileSize); qint64 len=tcpSocket->write(head.toUtf8()); if(len>0){ timer.start(20); }else{ qDebug()<<"头部信息发送失败"; file.close(); ui->btn_select->setEnabled(true); ui->btn_send->setEnabled(false); } } void MainWindow::sendData(){ qint64 len=0; do{ char buf[4*1024]={0}; len=0; len=file.read(buf,sizeof(buf)); len=tcpSocket->write(buf,len); sendSize+=len; }while(len>0); if(sendSize==fileSize){ ui->textEdit->append("文件发送完毕"); file.close(); tcpSocket->disconnectFromHost(); tcpSocket->close(); } }
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37
| #ifndef MAINWINDOW_H #define MAINWINDOW_H
#include <QMainWindow> #include <QTcpServer> #include <QTcpSocket> #include <QFile> #include <QTimer> namespace Ui { class MainWindow; }
class MainWindow : public QMainWindow { Q_OBJECT
public: explicit MainWindow(QWidget *parent = 0); ~MainWindow();
private slots: void on_btn_select_clicked();
void on_btn_send_clicked(); void sendData(); private: Ui::MainWindow *ui; QTcpServer *tcpServer; QTcpSocket *tcpSocket; QFile file; QString fileName; qint64 fileSize; qint64 sendSize; QTimer timer; };
#endif
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32
| #ifndef CLIENTWIDGET_H #define CLIENTWIDGET_H
#include <QWidget> #include <QTcpSocket> #include <QFile> namespace Ui { class ClientWidget; }
class ClientWidget : public QWidget { Q_OBJECT
public: explicit ClientWidget(QWidget *parent = 0); ~ClientWidget();
private slots: void on_btn_connect_clicked();
private: Ui::ClientWidget *ui; QTcpSocket *tcpSocket; QFile file; QString fileName; qint64 fileSize; qint64 recvSize; bool isStrat; };
#endif
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53
| #include "clientwidget.h" #include "ui_clientwidget.h" #include <QDebug> #include <QMessageBox> #include <QHostAddress> ClientWidget::ClientWidget(QWidget *parent) : QWidget(parent), ui(new Ui::ClientWidget) { ui->setupUi(this); isStrat=true; tcpSocket=new QTcpSocket(this); connect(tcpSocket,&QTcpSocket::readyRead,[=](){ QByteArray array=tcpSocket->readAll(); if(isStrat==true){ isStrat=false; fileName=QString(array).section("##",0,0); fileSize=QString(array).section("##",1,1).toInt(); recvSize=0;
file.setFileName(fileName); bool isOk=file.open(QIODevice::WriteOnly); if(isOk==false){ qDebug()<<"写失败"; } }else{ qint64 len=file.write(array); recvSize+=len; if(recvSize==fileSize){ file.close(); QMessageBox::information(this,"完成","文件接收完成"); tcpSocket->disconnectFromHost(); tcpSocket->close(); } } }); }
ClientWidget::~ClientWidget() { delete ui; }
void ClientWidget::on_btn_connect_clicked() { QString ip=ui->ip->text(); qint64 port=ui->port->text().toInt(); tcpSocket->connectToHost(QHostAddress(ip),port); }
|
线程
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| #ifndef MYTHREAD_H #define MYTHREAD_H
#include <QThread>
class Mythread : public QThread { Q_OBJECT public: explicit Mythread(QThread *parent = nullptr); protected: void run(); signals: void isDone(); public slots: };
#endif
|
1 2 3 4 5 6 7 8 9 10 11
| #include "mythread.h"
Mythread::Mythread(QThread *parent) : QThread(parent) {
} void Mythread::run(){ sleep(5); emit isDone(); }
|
1 2 3
| thread->quit(); thread->wait();
|
第二种方式见MyWidget项目
数据库
将libmysql.dll文件放到QT/bin下
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40
| QSqlDatabase db=QSqlDatabase::addDatabase("QMYSQL"); db.setHostName("localhost"); db.setUserName("root"); db.setPassword("123456"); db.setDatabaseName("student"); if(!db.open()){ qDebug()<<db.lastError().text(); return; } QSqlQuery query;
query.exec("select * from student"); while(query.next()){ qDebug()<<query.value(0).toString()<<query.value("xueHao").toString(); }
qDebug()<<query.exec("update student set zhuanYeBanJi='11' where xueHao = '181451081111'");
|
数据库控件直接操作数据库不需要命令
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39
| QSqlTableModel *model = new QSqlTableModel(this); model->setTable("student"); ui->tableView->setModel(model); model->select();
QItemSelectionModel *sModel=ui->tableView->selectionModel(); QModelIndexList list=sModel->selectedRows(); for(int i=0;i<list.size();i++) { model->removeRow(list.at(i).row()); }
model->setFilter(); model->select();
|