时钟:
widget.h:
- #ifndef WIDGET_H
- #define WIDGET_H
-
- #include
- #include
- #include
- #include
- #include
- #include
- #include
-
-
- QT_BEGIN_NAMESPACE
- namespace Ui { class Widget; }
- QT_END_NAMESPACE
-
- class Widget : public QWidget
- {
- Q_OBJECT
-
- public:
- Widget(QWidget *parent = nullptr);
- ~Widget();
-
- void paintEvent(QPaintEvent *event) override;
-
- void timerEvent(QTimerEvent *event) override;
-
- private:
- Ui::Widget *ui;
-
- QLabel *lab12;
- QLabel *lab3;
- QLabel *lab6;
- QLabel *lab9;
-
- int time_id;
-
- };
- #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);
- lab12 = new QLabel(this);
- lab12->setText("12");
- lab12->setFont(QFont("楷体",25,3));
- lab12->move(this->width()/2-20,this->height()/2-175);
-
- lab3 = new QLabel(this);
- lab3->setText("3");
- lab3->setFont(QFont("楷体",25,3));
- lab3->move(this->width()/2+150,this->height()/2-20);
-
- lab6 = new QLabel(this);
- lab6->setText("6");
- lab6->setFont(QFont("楷体",25,3));
- lab6->move(this->width()/2-10,this->height()/2+135);
-
- lab9 = new QLabel(this);
- lab9->setText("9");
- lab9->setFont(QFont("楷体",25,3));
- lab9->move(this->width()/2-160,this->height()/2-20);
-
- time_id = startTimer(1000);
- }
-
- Widget::~Widget()
- {
- delete ui;
- }
-
- void Widget::paintEvent(QPaintEvent *event)
- {
- //获取系统时间
- QTime sys_t = QTime::currentTime();
- int hour = sys_t.hour();
- int minute = sys_t.minute();
- int second = sys_t.second();
- //分刻度绘制
- QPainter painterMinute(this);
- QPen penMinute;
- penMinute.setStyle(Qt::SolidLine);
- penMinute.setWidth(5);
- painterMinute.setPen(penMinute);
- painterMinute.translate(this->width()/2,this->height()/2);
- painterMinute.drawEllipse(QPoint(0,0),200,200);
- for(int i = 0;i < 12;i++){
- painterMinute.drawLine(0,-200,0,-180);
- painterMinute.rotate(360/12);
- }
- //秒钟刻度绘制
- QPainter painterSecond(this);
- QPen penSecond;
- penSecond.setStyle(Qt::SolidLine);
- penSecond.setWidth(3);
- painterSecond.setPen(penSecond);
- painterSecond.translate(this->width()/2,this->height()/2);
- for(int i = 0;i < 60;i++){
- painterSecond.drawLine(0,-200,0,-190);
- painterSecond.rotate(360/60);
- }
- //时针绘制
- QPainter painterHourPoint(this);
- QPen penHourPoint;
- penHourPoint.setStyle(Qt::SolidLine);
- penHourPoint.setWidth(5);
- painterHourPoint.setPen(penHourPoint);
- painterHourPoint.translate(this->width()/2,this->height()/2);
- painterHourPoint.rotate((360/12)*(hour%12+minute/60+second/3600));
- painterHourPoint.drawLine(0,10,0,-50);
- //分针绘制
- QPainter painterMinutePoint(this);
- QPen penMinutePoint;
- penMinutePoint.setStyle(Qt::SolidLine);
- penMinutePoint.setWidth(4);
- painterMinutePoint.setPen(penMinutePoint);
- painterMinutePoint.translate(this->width()/2,this->height()/2);
- painterMinutePoint.rotate((360/60)*(minute+second/60));
- painterMinutePoint.drawLine(0,10,0,-150);
- //秒针绘制
- QPainter painterSecondPoint(this);
- QPen penSecondPoint;
- penSecondPoint.setStyle(Qt::SolidLine);
- penSecondPoint.setWidth(2);
- painterSecondPoint.setPen(penSecondPoint);
- painterSecondPoint.translate(this->width()/2,this->height()/2);
- painterSecondPoint.rotate((360/60)*second);
- painterSecondPoint.drawLine(0,10,0,-150);
- }
-
- void Widget::timerEvent(QTimerEvent *event)
- {
- if(time_id == event->timerId()){
- this->update();
- }
- }
-
效果图:
1> 实例化一个QTcpServer的类对象,那么一个服务器就创建好了
2> 调用服务器的listen函数,将服务器设置成监听状态,监听时,可以给定特定的主机地址,也可以监听所有主机地址;可以指定端口号访问该服务器,也可以由该服务器自动分配一个端口号
3> 此时,如果有客户端向服务器发来连接请求,那么该服务器就会自动发射一个newConnection信号,我们可以在该信号对应的槽函数中处理逻辑
4> 可以调用nextPaddingConnection获取最新连接的客户端套接字的地址,并将该地址,放入自己的客户端容器中
5> 如果有客户端向服务器发来数据,那么该客户端就会自动发射一个readyRead信号,我们可以在该信号对应槽函数中处理逻辑
6> 可以通过套接字的成员函数,完成数据通信,发送数据:write函数实现,接收数据:read、readLine、readAll实现
7> 可以调用成员函数close用于停止监听客户端的连接
案例
1、ui界面
2、配置文件
3、头文件
- #ifndef WIDGET_H
- #define WIDGET_H
-
-
- #include
- #include
//服务器头文件 - #include
//客户端头文件 - #include
//链表容器 - #include
//消息对话框 - #include
-
-
- QT_BEGIN_NAMESPACE
- namespace Ui { class Widget; }
- QT_END_NAMESPACE
-
-
- class Widget : public QWidget
- {
- Q_OBJECT
-
-
- public:
- Widget(QWidget *parent = nullptr);
- ~Widget();
-
-
- private slots:
- void on_startBtn_clicked();
-
-
- void newConnection_slot(); //自定义处理newConnection信号的槽函数的声明
- void readyRead_slot(); //自定义处理readyRead信号的槽函数的声明
-
-
- private:
- Ui::Widget *ui;
-
-
- //定义服务器指针
- QTcpServer *server;
-
-
- //定义客户端容器
- QList
clientList; -
-
- };
- #endif // WIDGET_H
4、源文件
- #include "widget.h"
- #include "ui_widget.h"
-
-
- Widget::Widget(QWidget *parent)
- : QWidget(parent)
- , ui(new Ui::Widget)
- {
- ui->setupUi(this);
-
-
- //实例化一个服务器
- server = new QTcpServer(this);
-
-
- //此时,服务器已经成功进入监听状态,如果有客户端向服务器发来连接请求
- //那么该服务器,就会自动发射一个newConnection的信号,我们可以将该信号连接到对应槽函数中执行相关逻辑
- //由于只需要连接一次即可,所以可以将该连接放在构造函数中完成
- connect(server, &QTcpServer::newConnection, this, &Widget::newConnection_slot);
- }
-
-
- Widget::~Widget()
- {
- delete ui;
- }
-
-
- //启动服务器按钮对应的槽函数
- void Widget::on_startBtn_clicked()
- {
- quint16 port = ui->portEdit->text().toUInt(); //获取ui界面上的端口号
-
-
- //监听客户端的连接请求
- //函数原型:bool listen(const QHostAddress &address = QHostAddress::Any, quint16 port = 0);
- //参数1:要监听的主机地址,如果是any表示监听任意一个主机地址,也可以是特定的主机地址
- //参数2:该服务器提供的端口号,如果是0,表示由服务器自动指定,一般由程序员指定
- //返回值:成功进入监听状态,返回true,其他情况返回false
- if(!server->listen(QHostAddress::Any, port))
- {
- QMessageBox::information(this, "失败", "监听失败");
- return ;
- }else
- {
- QMessageBox::information(this, "成功", "服务器启动成功");
- }
-
-
- //此时,服务器已经成功进入监听状态,如果有客户端向服务器发来连接请求
- //那么该服务器,就会自动发射一个newConnection的信号,我们可以将该信号连接到对应槽函数中执行相关逻辑
- //由于只需要连接一次即可,所以可以将该连接放在构造函数中完成
- }
-
-
- //自定义处理newConnection信号的槽函数的实现
- void Widget::newConnection_slot()
- {
- qDebug()<<"您有新的客户端发来连接请求了";
-
-
- //获取最新连接的客户端套接字
- //函数原型:virtual QTcpSocket *nextPendingConnection();
- //参数:无
- //返回值:最新连接过来的客户端套接字的地址
- QTcpSocket *s = server->nextPendingConnection();
-
-
- //将该套接字,放入客户端链表中
- clientList.push_back(s);
-
-
- //至此,多个客户端已经跟服务器建立连接,并放入客户端容器中了
- //此时,如果有客户端向服务器发来数据,那么对应的客户端套接字就会自动发射一个readyRead信号
- //我们可以将该信号连接到自定义的槽函数中,处理相关逻辑
- connect(s, &QTcpSocket::readyRead, this, &Widget::readyRead_slot);
- }
-
-
- //readyRead信号对应槽函数的实现
- void Widget::readyRead_slot()
- {
- qDebug()<<"有新的客户端消息发来了";
-
-
- //遍历客户端链表,将无效的客户端移除
- for(int i=0; i
size(); i++) - {
- //判断当前套接字是否是有效连接
- //函数原型: SocketState state() const;
- //参数:无
- //返回值:套接字的状态,如果是0,表示该套接字为无效连接
- if(clientList[i]->state() ==0)
- {
- //将该套接字移除客户端容器
- clientList.removeAt(i);
- }
- }
-
-
- //遍历客户端链表,判断是哪个客户端发来的数据
- for(int i=0; i
size(); i++) - {
- //函数原型:qint64 bytesAvailable() const override;
- //功能:求当前客户端套接字中待读数据的字节数
- //参数:无
- //返回值:待读数据的字节数,如果是0,表示无数据待读
- if(clientList[i]->bytesAvailable() != 0)
- {
- //将该套接字中的数据读取出来
- QByteArray msg = clientList[i]->readAll();
-
-
- //将数据展示到ui界面
- ui->msgWidget->addItem( QString::fromLocal8Bit(msg) );
-
-
- //将接受到的数据,转发给所有客户端
- for(int j=0; j
size(); j++) - {
- clientList[j]->write(msg);
- }
- }
- }
- }
1> 实例化一个QTcpSocket的对象,此时就创建了一个客户端了
2> 使用该类提供的成员函数connectToHost,向服务器发送连接请求,调用该函数时,需要指定服务器的主机地址和端口号
3> 如果成功连接客户端,那么该客户端就会自动发射一个connected的信号,我们可以在该信号对应的槽函数中处理相关逻辑
4> 此时,客户端和服务就已经建立起来连接了,如果客户端接收到服务器发来的数据,那么该客户端就会自动发射一个readyRead信号
5> 在该信号对应的槽函数中,可以使用成员函数,完成数据通信,发送数据:write函数实现,接收数据:read、readLine、readAll实现
6> 断开连接,使用成员函数disconnectFromHost,如果成功断开连接,该客户端就会自动发射一个disconnected的信号
7> 我们可以在该信号处理函数中处理相关逻辑
案例
1、ui界面
2、配置文件
3、头文件
- #ifndef WIDGET_H
- #define WIDGET_H
-
-
- #include
- #include
//客户端类 - #include
-
-
- QT_BEGIN_NAMESPACE
- namespace Ui { class Widget; }
- QT_END_NAMESPACE
-
-
- class Widget : public QWidget
- {
- Q_OBJECT
-
-
- public:
- Widget(QWidget *parent = nullptr);
- ~Widget();
-
-
- private slots:
- void on_connectBtn_clicked();
- void connected_slot(); //自定义处理connected信号的槽函数的声明
- void readyRead_slot(); //自定义处理readyRead信号的槽函数的声明
-
-
- void on_sendBtn_clicked();
-
-
- void on_disconnectBtn_clicked();
-
-
- void disconnected_slot(); //自定义处理disconnected信号的槽函数的声明
-
-
- private:
- Ui::Widget *ui;
-
-
- //定义客户端指针
- QTcpSocket * socket;
-
-
- //定义字符串接受用户
- QString userName;
-
-
- };
- #endif // WIDGET_H
4、源文件
- #include "widget.h"
- #include "ui_widget.h"
-
-
- Widget::Widget(QWidget *parent)
- : QWidget(parent)
- , ui(new Ui::Widget)
- {
- ui->setupUi(this);
-
-
- //给客户端指针实例化对象
- socket = new QTcpSocket(this);
-
-
- //此时,已经向服务器发送连接请求了,如果成功连接服务器,那么该客户端就会自动发射一个connected的信号
- //我们可以将该信号连接到自定义的槽函数中处理逻辑
- //由于只需要连接一次,所以将连接写在构造函数中
- connect(socket, &QTcpSocket::connected, this, &Widget::connected_slot);
-
-
- //如果服务器向客户端发来消息,那么该客户端就会自动发射一个readyRead信号
- //我们可以将该进行连接到自定义的槽函数中处理相关逻辑
- connect(socket, &QTcpSocket::readyRead, this, &Widget::readyRead_slot);
-
-
- //当成功与服务器断开连接后,该客户端会自动发射一个disconnected的信号
- //我们可以将该信号连接到自定义的槽函数中处理相关逻辑
- //由于该连接只需连接一次即可,所以放在构造函数中进行
- connect(socket, &QTcpSocket::disconnected, this, &Widget::disconnected_slot);
-
-
- }
-
-
- Widget::~Widget()
- {
- delete ui;
- }
-
-
- //连接服务器按钮对应的槽函数
- void Widget::on_connectBtn_clicked()
- {
- //获取ui界面上的相关信息
- userName = ui->userNameEdit->text(); //获取用户名
- QString ip = ui->ipEdit->text(); //主机地址
- quint16 port = ui->portEdit->text().toUInt(); //端口号
-
-
-
-
- //函数原型:virtual void connectToHost(const QHostAddress &address, quint16 port);
- //功能:将客户端连接到给定的服务器
- //参数1:服务器的主机地址
- //参数2:端口号
- //返回值:无
- socket->connectToHost(ip, port);
-
-
- //此时,已经向服务器发送连接请求了,如果成功连接服务器,那么该客户端就会自动发射一个connected的信号
- //我们可以将该信号连接到自定义的槽函数中处理逻辑
- //由于只需要连接一次,所以将连接写在构造函数中
-
-
- }
-
-
-
-
- //处理connected信号的槽函数的定义
- void Widget::connected_slot()
- {
- QMessageBox::information(this, "成功", "您已经成功进入聊天室");
- //向服务器发送一条数据:***:进入聊天室
- QString msg = userName +": 进入聊天室";
-
-
- socket->write(msg.toLocal8Bit()); //将数据写给服务器
- }
-
-
- //处理readyRead信号的槽函数的定义
- void Widget::readyRead_slot()
- {
- //读取套接字中的信息
- QByteArray msg = socket->readAll();
-
-
- //将数据展示到ui界面
- ui->msgWidget->addItem(QString::fromLocal8Bit(msg));
- }
-
-
-
-
- //发送按钮对应的槽函数
- void Widget::on_sendBtn_clicked()
- {
- //获取ui界面输入的内容
- QString msg =userName+ ": " + ui->msgEdit->text();
-
-
- //发送给服务器
- socket->write(msg.toLocal8Bit());
-
-
- //清空编辑框内容
- ui->msgEdit->clear();
- }
-
-
- //断开服务器按钮对应的槽函数
- void Widget::on_disconnectBtn_clicked()
- {
- //告诉大家我走了
- QString msg = userName +": 离开聊天室";
- socket->write(msg.toLocal8Bit());
-
-
- //断开连接
- //函数原型: virtual void disconnectFromHost();
- socket->disconnectFromHost();
-
-
- //当成功与服务器断开连接后,该客户端会自动发射一个disconnected的信号
- //我们可以将该信号连接到自定义的槽函数中处理相关逻辑
- //由于该连接只需连接一次即可,所以放在构造函数中进行
- }
-
-
- //disconnected信号对应槽函数的定义
- void Widget::disconnected_slot()
- {
- QMessageBox::information(this, "提示", "退出成功");
- }
1> 数据库驱动层:QSqlDriver、QSqlDriverCreator、QSqlDriverCreatorBase、QSqlDriverPlugin
2> sql接口层:QSqlDatabase、QSqlQuery、QSqlRecord、QSqlError
3> 用户接口层:提供一些模型QSqlQueryModel、QSqlTableModel、QSqlRelationalTableModel
- 1、添加数据库:[static] QSqlDatabase QSqlDatabase::addDatabase(QSqlDriver *driver, const QString &connectionName = QLatin1String(defaultConnection))
-
- QSQLITE
- SQLite version 3 or above
- 2、设置数据库名称:void QSqlDatabase::setDatabaseName(const QString &name)
- 3、包含数据库:bool QSqlDatabase::contains(const QString &connectionName = QLatin1String(defaultConnection))
- 4、打开数据库:bool QSqlDriver::open(const QString &db)
- 5、关闭数据库:void QSqlDatabase::close()
- 6、错误信息:QSqlError QSqlDatabase::lastError()
- 7、sql语句执行:构造一个QSqlQuery类对象,调用其成员函数exec,执行sql语句:bool QSqlQuery::exec(const QString &query)
- 8、bool QSqlQuery::next():遍历查询结果的函数
1> ui界面
2> 配置文件
3> 头文件
- #ifndef WIDGET_H
- #define WIDGET_H
-
-
- #include
- #include
//数据库管理类 - #include
//执行sql语句的类 - #include
//数据库记录的类 - #include
//消息对话框 - #include
-
-
- QT_BEGIN_NAMESPACE
- namespace Ui { class Widget; }
- QT_END_NAMESPACE
-
-
- class Widget : public QWidget
- {
- Q_OBJECT
-
-
- public:
- Widget(QWidget *parent = nullptr);
- ~Widget();
-
-
- private slots:
- void on_insertBtn_clicked();
-
-
- void on_showBtn_clicked();
-
-
- private:
- Ui::Widget *ui;
-
-
- QSqlDatabase db; //定义一个数据库的类对象
- };
- #endif // WIDGET_H
4> 源文件
- #include "widget.h"
- #include "ui_widget.h"
-
-
- Widget::Widget(QWidget *parent)
- : QWidget(parent)
- , ui(new Ui::Widget)
- {
- ui->setupUi(this);
-
-
- //判断自己的数据库对象中,是否包含了要处理的数据库,如果没有包含则添加一个数据库,如果包含了,就可以打开了
- if(!db.contains("mydatabase.db"))
- {
- //添加一个数据库,调用该类中的静态成员函数addDatabase
- //函数原型:static QSqlDatabase addDatabase(const QString& type);
- //参数:驱动类型 QSQLITE SQLite version 3
- //返回值:数据库对象
- db = QSqlDatabase::addDatabase("QSQLITE");
-
-
- //设置数据库的名字
- db.setDatabaseName("mydatabase.db");
- }
-
-
- //此时已经有一个名为mydatabase.db的数据库
- //打开数据库
- if(!db.open())
- {
- QMessageBox::information(this,"失败","数据库打开失败");
- return;
- }
-
-
- //需要使用sql语句进行创建表的操作
- //准备sql语句
- QString sql = "create table if not exists stu_info(" //创建表
- "numb integer primary key," //学号,主键
- "name varchar(10)," //姓名
- "sex varchar(2)," //性别
- "score integer)"; //成绩
- //准备语句执行者
- QSqlQuery querry;
-
-
- //让语句执行者执行sql语句
- //函数原型:bool exec(const QString& query);
- //参数:要执行的sql语句
- //返回值:成功执行返回true,失败返回false
- if(!querry.exec(sql))
- {
- QMessageBox::information(this, "失败", "创建表失败");
- return;
- }
- }
-
-
- Widget::~Widget()
- {
- delete ui;
- }
-
-
- //录入按钮对应的槽函数
- void Widget::on_insertBtn_clicked()
- {
- //获取ui界面中要录入的数据
- int numb = ui->numbEdit->text().toInt();
- QString name = ui->nameEdit->text();
- QString sex = ui->sexEdit->text();
- int score = ui->scoreEdit->text().toInt();
-
-
- //要确保每个编辑器中都有数据
- if(numb==0 || name.isEmpty() || sex.isEmpty() || score==0)
- {
- QMessageBox::information(this,"提示","请将信息填写完整");
- return;
- }
-
-
- //准备sql语句
- QString sql = QString("insert into stu_info(numb, name, sex, score) "
- "values(%1, '%2', '%3', %4)").arg(numb).arg(name).arg(sex).arg(score);
-
-
- //qDebug()<
- //准备语句执行者
- QSqlQuery querry;
- if(!querry.exec(sql))
- {
- QMessageBox::information(this,"失败", "添加失败");
- return;
- }else
- {
- QMessageBox::information(this,"成功", "添加成功");
- }
- }
-
-
-
-
-
-
-
-
- //显示按钮对应的槽函数
- void Widget::on_showBtn_clicked()
- {
- //准备sql语句
- QString sql = "select * from stu_info";
-
-
- //准备语句执行者
- QSqlQuery querry;
-
-
- //执行sql语句
- if(!querry.exec(sql))
- {
- QMessageBox::information(this,"提示","显示失败");
- return;
- }
-
-
- //此时,已经完成查询工作,并且将查询的结果全部都放入querry类对象中
- //要遍历查询结果,可以使用QSqlQuerry类中的成员函数next
- int i = 0; //记录行数
- while(querry.next())
- {
- //在该循环中,querry对象表示的是当前的记录
- //可以使用成员函数: QSqlRecord record() const;获取当前记录
- //可以使用QSqlRecord成员函数,count():获取当前记录中的项数
- //可以使用QSqlRecord成员函数,value(index):获取当前记录中第index项的值
- //qDebug()<
-
-
- //遍历每条记录中的每一项的内容
- for(int j=0; j
record().count(); j++) - {
- //qDebug()<
- ui->tableWidget->setItem(i,j, new QTableWidgetItem(querry.record().value(j).toString()));
- }
-
-
-
-
- i++; //继续遍历下一条记录
- }
- }