QT:基于QT实现Boost搜索引擎客户端

文章目录

  • 写在前面
    • 关于服务器
    • 开源仓库和项目上线
    • 其他文档说明
  • 登录界面
    • 主体设计思路
    • 验证登录
    • 注册功能
  • 注册界面
  • 主体界面
  • main函数中绑定槽函数

写在前面

关于服务器

本项目使用的是一个仿mudou库one-thread-one-loop式并发服务器的组件,关于该组件的细节内容在下面的链接中:

仿mudou库one-thread-one-loop式并发服务器

自主实现Boost搜索引擎

开源仓库和项目上线

本项目已开源到下面链接下的仓库当中

search-engine-online

并且项目已经部署在了Linux服务器上,具体访问方式可以点击下面链接进行访问:

81.70.160.28:8081

其他文档说明

针对于日志的信息,我采用了之前写的一份利用可变参数实现日志的代码,具体链接如下

C++:可变参数实现日志系统

这是一篇使用QT框架来实现一个配套与Boost搜索引擎的客户端的制作文档

登录界面

主体设计思路

首先设计一个简单的登陆界面

并且给对应的按钮提供对应的槽函数,如果验证成功了,就直接跳转到一个主页面

验证登录

下面是对于验证登录的逻辑,由于是连接到数据库的,所以这里需要用到网络通信,一个大体的思路就是把账号和密码提取出来,然后通过网络传输过去,在后端进行分析,再返回来,这里直接使用QT框架现成的Http部分

void Login::on_pushButton_login_clicked()
{
    // 点击登录后先验证账号和密码
    // 把账号和密码提取出来
    const QString& username = ui->lineEdit_account->text();
    const QString& password = ui->lineEdit_passwd->text();
    sender(username, password);
}

void Login::sender(const QString &username, const QString &password)
{
    // 1. 获取到输入框中的 URL, 构造 QUrl 对象
    QUrl url(serverurl);

    // 2. 构造 HTTP 请求对象,并设置请求头
    QNetworkRequest request(url);
    request.setHeader(QNetworkRequest::ContentTypeHeader, "application/json");

    // 创建 JSON 文档并填充数据
    QJsonObject jsonObject;
    jsonObject["username"] = username;
    jsonObject["password"] = password;

    // 将 JSON 文档转换为 QByteArray
    QJsonDocument jsonDoc(jsonObject);
    QByteArray postData = jsonDoc.toJson();

    // 3. 发送 POST 请求(这次包含JSON数据主体)
    QNetworkReply* response = manager->post(request, postData);

    // 4. 通过信号槽来处理响应
    connect(response, &QNetworkReply::finished, this, [=]() {
        if (response->error() == QNetworkReply::NoError)
        {
            // 响应正确
            QString html(response->readAll());
            qDebug() << "Response:" << html;
            // 验证正确后跳转到对应界面
            QMessageBox box(QMessageBox::Information, "提示", "登录成功", QMessageBox::Ok, this);
            int ret = box.exec();
            if(ret == QMessageBox::Ok)
            {
                this->close();
                this->sig_mainwindow();
            }
        }
        else
        {
            // 响应出错
            QString error = response->errorString();
            qDebug() << "Error:" << error;
            qDebug() << "账号或密码错误";
            int ret = QMessageBox::information(this, "提示", "账号或密码输入错误, 是否重新登录", QMessageBox::Yes | QMessageBox::No);
            if(ret == QMessageBox::Yes)
                ui->lineEdit_passwd->clear();
            else
                this->close();
        }
        response->deleteLater();
    });
}

至于验证登录的逻辑,这里不显示,因为这是后端已经完成的部分

注册功能

void Login::on_pushButton_register_clicked()
{
    this->sig_register();
}

注册界面

这个界面也没什么好说的,和登录界面的逻辑基本一样,只是调用服务端的API即可

#include "register.h"
#include "ui_register.h"
#include <QMessageBox>
#include <QGridLayout>
#include <QString>
#include <QMessageBox>
#include <QJsonObject>
#include <QDebug>
#include <QJsonDocument>
#include <QNetworkAccessManager>
#include <QNetworkReply>
#include <QNetworkRequest>

const QString& serverreq = "http://62.234.180.244:8081/register";

Register::Register(QWidget *parent) :
    QDialog(parent),
    ui(new Ui::Register)
{
    ui->setupUi(this);

    // 设置一下标题和图标
    this->setWindowTitle("注册");
    this->setWindowIcon(QIcon(QPixmap(":/imag/register.png")));

    // 实例化对象
    manager = new QNetworkAccessManager(this);
}

Register::~Register()
{
    delete ui;
}

void Register::jump()
{
    this->show();
}

void Register::on_pushButton_register_clicked()
{
    // 点击注册后先验证账号和密码
    // 把账号和密码提取出来
    const QString& username = ui->lineEdit_account->text();
    const QString& password = ui->lineEdit_passwd->text();
    sender(username, password);
}

void Register::sender(const QString &username, const QString &password)
{
    // 1. 获取到输入框中的 URL, 构造 QUrl 对象
    QUrl url(serverreq);

    // 2. 构造 HTTP 请求对象,并设置请求头
    QNetworkRequest request(url);
    request.setHeader(QNetworkRequest::ContentTypeHeader, "application/json");

    // 创建 JSON 文档并填充数据
    QJsonObject jsonObject;
    jsonObject["username"] = username;
    jsonObject["password"] = password;

    // 将 JSON 文档转换为 QByteArray
    QJsonDocument jsonDoc(jsonObject);
    QByteArray postData = jsonDoc.toJson();

    // 3. 发送 POST 请求(这次包含JSON数据主体)
    QNetworkReply* response = manager->post(request, postData);

    // 4. 通过信号槽来处理响应
    connect(response, &QNetworkReply::finished, this, [=]() {
        if (response->error() == QNetworkReply::NoError)
        {
            // 响应正确
            QString html(response->readAll());
            qDebug() << "Response:" << html;
            // 验证正确后跳转到对应界面
            QMessageBox box(QMessageBox::Information, "提示", "注册成功", QMessageBox::Ok, this);
            int ret = box.exec();
            if(ret == QMessageBox::Ok)
            {
                this->close();
            }
        }
        else
        {
            // 响应出错
            QString error = response->errorString();
            qDebug() << "Error:" << error;
            qDebug() << "用户名重复!";
            int ret = QMessageBox::information(this, "提示", "用户名重复!是否重新注册", QMessageBox::Yes | QMessageBox::No);
            if(ret == QMessageBox::Yes)
                ui->lineEdit_passwd->clear();
            else
                this->close();
        }
        response->deleteLater();
    });
}

主体界面

#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QMessageBox>
#include <QGridLayout>
#include <QString>
#include <QMessageBox>
#include <QJsonObject>
#include <QDebug>
#include <QJsonDocument>
#include <QNetworkAccessManager>
#include <QNetworkReply>
#include <QNetworkRequest>
#include <QUrlQuery>
#include <QJsonArray>

const QString& server_search = "http://62.234.180.244:8081/s";
const QString& server_hotwords = "http://62.234.180.244:8081/hotwords";

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
{
    ui->setupUi(this);

    // 设置一下标题和图标
    this->setWindowTitle("查找");
    this->setWindowIcon(QIcon(QPixmap(":/imag/search.png")));

    // 实例化对象
    manager = new QNetworkAccessManager(this);
}

MainWindow::~MainWindow()
{
    delete ui;
}

void MainWindow::jump()
{
    this->show();
}

void MainWindow::on_pushButton_clicked()
{
    // 当点击搜索按钮时,要传递一个/s请求
    // 0. 获取到用户要搜索的关键字
    const QString& user_search = ui->lineEdit_search->text();
    // 1. 获取到输⼊框中的 URL, 构造 QUrl 对象
    QUrl url(server_search);
    // 2. 将用户搜索的关键字作为查询参数添加到URL中,构造 HTTP 请求对象
    QUrlQuery query;
    query.addQueryItem("word", user_search);
    url.setQuery(query);
    QNetworkRequest request(url);
    // 3. 发送 GET 请求
    QNetworkReply* response = manager->get(request);
    // 4. 通过信号槽来处理响应
    connect(response, &QNetworkReply::finished, this, [=]()
    {
        if (response->error() == QNetworkReply::NoError)
        {
            QString html(response->readAll());
            displaySearchResults(html);
        }
        else
        {
            ui->plainTextEdit->setPlainText(response->errorString());
        }
        response->deleteLater();
    });
    // 点击搜索的时候也把热词统计显示出来
    handle_hotwords();
}

void MainWindow::on_pushButton_2_clicked()
{
    handle_hotwords();
}

void MainWindow::handle_hotwords()
{
    // 当点击搜索按钮时,要传递一个/s请求
    // 1. 获取到输⼊框中的 URL, 构造 QUrl 对象
    QUrl url(server_hotwords);
    // 2. 将用户搜索的关键字作为查询参数添加到URL中,构造 HTTP 请求对象
    QNetworkRequest request(url);
    // 3. 发送 GET 请求
    QNetworkReply* response = manager->get(request);
    // 4. 通过信号槽来处理响应
    connect(response, &QNetworkReply::finished, this, [=]()
    {
        if (response->error() == QNetworkReply::NoError)
        {
            QString html(response->readAll());
            displayHotWords(html);
        }
        else
        {
            ui->plainTextEdit_2->setPlainText(response->errorString());
        }
        response->deleteLater();
    });
}

void MainWindow::displaySearchResults(const QString &jsonData)
{
    QJsonDocument doc = QJsonDocument::fromJson(jsonData.toUtf8());
    if (!doc.isArray())
    {
        ui->plainTextEdit->setPlainText("解析结果错误,不是有效的JSON数组");
        return;
    }

    QStringList formattedResults;
    const QJsonArray results = doc.array();
    for (const QJsonValue &result : results)
    {
        if (result.isObject())
        {
            const QJsonObject obj = result.toObject();
            QString title = obj["title"].toString();
            QString desc = obj["desc"].toString();
            QString url = obj["url"].toString();
            QString line = QString("%1\n%2\n%3\n").arg(title, desc, url);
            formattedResults.append(line);
            // formattedResults.append("\n");
        }
    }

    ui->plainTextEdit->setPlainText(formattedResults.join("\n"));
}

void MainWindow::displayHotWords(const QString &jsonData)
{
    QJsonDocument doc = QJsonDocument::fromJson(jsonData.toUtf8());
    if (!doc.isObject())
    {
        ui->plainTextEdit_2->setPlainText("解析结果错误,不是有效的JSON对象");
        return;
    }

    QJsonObject jsonObj = doc.object();
    if (!jsonObj.contains("hotWords") || !jsonObj["hotWords"].isArray())
    {
        ui->plainTextEdit_2->setPlainText("未找到或'hotWords'不是数组");
        return;
    }

    const QJsonArray hotWordsArray = jsonObj["hotWords"].toArray();
    QStringList formattedHotWords;

    for (const QJsonValue &wordObj : hotWordsArray)
    {
        if (wordObj.isObject())
        {
            QJsonObject word = wordObj.toObject();
            int count = word["count"].toInt();
            QString wordStr = word["word"].toString();
            QString line = QString("%1 :%2次\n").arg(wordStr, QString::number(count));
            formattedHotWords.append(line);
        }
    }

    // 添加分隔符或自定义样式后,设置到plainTextEdit中
    ui->plainTextEdit_2->setPlainText(formattedHotWords.join("\n"));
}

main函数中绑定槽函数

#include "mainwindow.h"
#include "login.h"
#include "register.h"
#include <QApplication>

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    Login log;
    log.show();
    MainWindow mainwindow;
    Register registerPage; // 创建Register类的实例

    // 建立两个槽,一个跳转到mainwindow,一个跳转到register
    QObject::connect(&log, &Login::sig_mainwindow, &mainwindow, &MainWindow::jump);
    QObject::connect(&log, &Login::sig_register, &registerPage, &Register::jump); // 修正接收对象为registerPage实例

    return a.exec();
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/599883.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

基于FPGA的DDS波形发生器VHDL代码Quartus仿真

名称&#xff1a;基于FPGA的DDS波形发生器VHDL代码Quartus仿真&#xff08;文末获取&#xff09; 软件&#xff1a;Quartus 语言&#xff1a;VHDL 代码功能&#xff1a; DDS波形发生器VHDL 1、可以输出正弦波、方波、三角波 2、可以控制输出波形的频率 DDS波形发生器原理…

学习和分析各种数据结构所要掌握的一个重要知识——CPU的缓存利用率(命中率)

什么是CPU缓存利用率&#xff08;命中率&#xff09;&#xff0c;我们首先要把内存搞清楚。 硬盘是什么&#xff0c;内存是什么&#xff0c;高速缓存是什么&#xff0c;寄存器又是什么&#xff1f; 我们要储存数据就要运用到上面的东西。首先里面的硬盘是可以无电存储的&#…

无人零售,重塑购物新纪元

在这个快节奏的时代&#xff0c;科技的每一次跃进都在悄无声息地改变着我们的生活方式。而今&#xff0c;无人零售正以雷霆之势&#xff0c;颠覆传统购物模式&#xff0c;为我们带来前所未有的便捷与智能体验。想知道无人零售如何彻底改变我们的购物方式吗&#xff1f;跟随我&a…

Linux实现Flappy bird项目

目录 1、项目介绍 2、功能总结 3、前期准备 3.1 Ncurses库 3.2 信号机制 3.2.1 设置信号响应方式 3.2.2 设置定时器 4、代码实现 4.1 头文件引用及变量、函数定义 4.2 主函数 4.3 curses初始化 4.4 设置定时器 4.5 定时器响应函数 4.6 小鸟控制相关函数 4…

Java的Fork-Join简单介绍

Java的Fork-Join框架是Java 7引入的一个用于并行处理的轻量级框架&#xff0c;它基于分治策略&#xff08;Divide and Conquer&#xff09;&#xff0c;特别适合于那些可以被分解为多个子任务的任务。Fork-Join框架的核心思想是将一个大任务&#xff08;Task&#xff09;拆分成…

毕业就业信息|基于Springboot+vue的毕业就业信息管理系统的设计与实现(源码+数据库+文档)

毕业就业信息管理系统 目录 基于Springboot&#xff0b;vue的毕业就业信息管理系统设计与实现 一、前言 二、系统设计 三、系统功能设计 1学生信息管理 2 公司信息管理 3公告类型管理 4公告信息管理 四、数据库设计 五、核心代码 六、论文参考 七、最新计算机毕设…

高等数学笔记(下中)

曲线积分 第一类曲线积分&#xff1a;对弧长的积分计算方法 定理&#xff1a;设 f ( x , y ) f(x,y) f(x,y)在曲线弧 L L L上有定义且连续&#xff0c; L L L的参数方程是 { x φ ( t ) y ψ ( t ) ( α ≤ t ≤ β ) \begin{cases} x\varphi(t)\\ y\psi(t) \end{cases}(\a…

Python实现打砖块游戏

提供学习或者毕业设计使用&#xff0c;功能基本都有&#xff0c;不能和市场上正式游戏相提比论&#xff0c;请理性对待&#xff01; 在本文中&#xff0c;我们将使用 Pygame 和 Tkinter 创建一个简单的打砖块游戏。游戏的目标是通过控制挡板来击碎屏幕上的砖块&#xff0c;同时…

PTQ4SAM、Mamba-Attention、AniTalker、IceFormer、U-DiTs、CogDPM

本文首发于公众号&#xff1a;机器感知 PTQ4SAM、Mamba-Attention、AniTalker、IceFormer、U-DiTs、CogDPM PTQ4SAM: Post-Training Quantization for Segment Anything Segment Anything Model (SAM) has achieved impressive performance in many computer vision tasks. Ho…

华为机考入门python3--(23)牛客23- 删除字符串中出现次数最少的字符

分类&#xff1a;字符串 知识点&#xff1a; 访问字典中keychar的值&#xff0c;不存在则返回0 my_dict.get(char, 0) 字典的所有值 my_dict.value() 列表中的最小值 min(my_list) 题目来自【牛客】 import sysdef delete_min_freq_char(s):# 计算字母出现的频次…

套管外径测量仪 多尺寸型号 规格全可定制

套管&#xff08;bushing&#xff09;是一种将带电导体引入电气设备或穿过墙壁的一种绝缘装置。前者称为电器套管&#xff0c;后者称为穿墙套管。套管通常用在建筑地下室&#xff0c;是用来保护管道或者方便管道安装的铁圈。套管的分类有刚性套管、柔性防水套管、钢管套管及铁皮…

鸿蒙OpenHarmony实战开发-MiniCanvas

介绍 基于OpenHarmony的Cavas组件封装了一版极简操作的MiniCanvas&#xff0c;屏蔽了原有Canvas内部复杂的调用流程&#xff0c;支持一个API就可以实现相应的绘制能力&#xff0c;该库还在继续完善中&#xff0c;也欢迎PR。 使用说明 1.添加MiniCanvas依赖 在项目entry目录…

07 - 步骤 javaScript代码

简介 JavaScript 代码是通过 JavaScript 脚本步骤来执行 JavaScript 脚本的一种方式。这允许用户在 Kettle 的数据流程中使用 JavaScript 编写自定义的脚本逻辑&#xff0c;用于数据处理、转换、计算等操作。 使用 场景 我需要在数据流加一个字段 createTime 当前时间&…

【嵌入式DIY实例】-基于GSM的远程灌溉系统

基于GSM的远程灌溉系统 文章目录 基于GSM的远程灌溉系统1、硬件准备与接线2、软件准备3、代码实现本文将详细介绍如何搭建通过使用手机实现对灌溉系统的远程控制。该系统利用全球移动通信系统(GSM)技术在灌溉系统和移动电话之间建立通信。该系统建立在流行的开源微控制器平台…

Linux 进程间通信之共享内存

&#x1f493;博主CSDN主页:麻辣韭菜&#x1f493;   ⏩专栏分类&#xff1a;Linux知识分享⏪   &#x1f69a;代码仓库:Linux代码练习&#x1f69a;   &#x1f339;关注我&#x1faf5;带你学习更多Linux知识   &#x1f51d; ​ 目录 ​编辑​ 前言 共享内存直接原理…

使用双指针解决问题题集(二)

1. 有效三角形的个数 给定一个包含非负整数的数组 nums &#xff0c;返回其中可以组成三角形三条边的三元组个数。 示例 1: 输入: nums [2,2,3,4] 输出: 3 解释:有效的组合是: 2,3,4 (使用第一个 2) 2,3,4 (使用第二个 2) 2,2,3 示例 2: 输入: nums [4,2,3,4] 输出: 4 题解&a…

zabbix监控方式(zabbix-trapper)

中文&#xff1a;zabbix采集器&#xff0c;即zabbix sender 。 Zabbix-Trapper 监控方式可以一次批量发送数据给Zabbix Server&#xff0c;与主动模式不同&#xff0c;Zabbix-Trapper 可以让用户控制数据的发送&#xff0c;而不用Zabbix-Agent进程控制&#xff0c;这意味着可以…

Angular中的管道(Pipe)

Angular中的管道(Pipe) 文章目录 Angular中的管道(Pipe)前言一、内置管道1. date管道格式化日期2. currency管道格式化货币3. uppercase和lowercase管道转换字符串大小写4. 小数位数5. JavaScript 对象序列化6. slice7. 管道链 二、自定义管道 前言 Angular中的管道&#xff0…

力扣刷题--数组--第二天

今天仍然做二分查找相关的题目。先来回顾一下二分查找的方法和使用的条件。二分查找是在数组中查找目标值的一种方法&#xff0c;通过边界索引确定中间索引&#xff0c;判断中间索引处的元素值和目标值的大小&#xff0c;来不断缩小查找区间。使用二分查找有如下一些限制&#…

ASP.NET通用作业批改系统设计

摘  要 该系统采用B/S结构&#xff0c;以浏览器方式登陆系统&#xff0c;用ASP.NET作为开发语言&#xff0c;数据库则使用Microsoft SQL Server 2000实现。《通用作业批改系统》包括了学生子系统、教师子系统、管理员子系统三大模块&#xff0c;该系统主要完成学生&#xff…
最新文章