当前位置: 首页 > news >正文

Leather Dress Collection 快速原型开发:使用 Qt 构建图形化测试客户端

Leather Dress Collection 快速原型开发:使用 Qt 构建图形化测试客户端

你是不是也遇到过这种情况?好不容易把那个酷炫的AI模型部署好了,API接口也调通了,但每次想测试一下效果,都得打开终端敲命令,或者写个简陋的脚本。想给同事或老板演示一下?那就更麻烦了,总不能让他们也对着黑乎乎的终端窗口吧。

今天,我就带你用 Qt 快速搞一个桌面版的测试客户端。不用太复杂,就一个能输入文字、点击按钮、然后漂亮地展示生成结果的窗口程序。这样一来,无论是自己日常测试模型效果,还是给非技术同事做个演示,都方便多了。整个过程就像搭积木一样简单,哪怕你之前没怎么用过 Qt,跟着走一遍也能搞定。

咱们这个客户端的目标很明确:做一个美观、易用的图形界面,把调用模型、处理结果这些“脏活累活”都封装起来。你只需要关心输入什么、看到什么结果就行。

1. 环境准备与项目创建

工欲善其事,必先利其器。我们先来把开发环境搭好。

1.1 安装 Qt 开发环境

首先,你需要安装 Qt。如果你用的是 Windows 或 macOS,我强烈建议直接下载 Qt 的在线安装器,它比较省心。去 Qt 官网找到下载页面,选择那个Qt Online Installer

运行安装器后,它会让你选择组件。对于咱们这个项目,你只需要确保勾选了以下两项就足够了:

  • Qt 6.x.x:选择最新的稳定版,比如 Qt 6.5 或 6.6。记得勾选对应你编译器的版本,比如 MSVC 2019 64-bit(如果你用 Visual Studio)或者 MinGW 64-bit。
  • Qt Creator:这是 Qt 官方的集成开发环境(IDE),界面友好,对新手特别友好,我们后续就用它来写代码和构建项目。

安装过程可能需要一点时间,喝杯咖啡等着就行。安装完成后,打开 Qt Creator,我们准备创建新项目。

1.2 创建 Qt Widgets 项目

打开 Qt Creator 后,点击左上角的File->New File or Project...

  1. 在弹窗里,选择Application->Qt Widgets Application,然后点击Choose...
  2. 给项目起个名字,比如LeatherDressClient,选个你喜欢的项目存放路径。
  3. Kit Selection页面,确保勾选了刚才安装的 Qt 套件(比如Desktop Qt 6.5.0 MSVC2019 64bit)。
  4. 后续的类信息页面保持默认就行,直接点击Finish

恭喜,Qt Creator 已经为你生成了一个最基本的、带有一个空白窗口的应用程序项目。你可以点击左下角的绿色三角按钮(或按Ctrl+R)运行一下,看看这个空窗口长什么样。

2. 设计客户端界面

界面是用户看到的第一眼,咱们把它设计得清晰明了。Qt 提供了一个叫Qt Designer的可视化工具,拖拖拽拽就能搞定,不需要手写一堆界面布局代码。

2.1 使用 Qt Designer 布局

在 Qt Creator 左侧的项目文件列表里,找到Forms文件夹下的mainwindow.ui文件,双击它。这会打开内置的 Qt Designer。

我们的界面可以这样规划:

  • 顶部:一个输入框,让用户输入描述皮革连衣裙的文本。
  • 中部:一个按钮,点击后开始生成。
  • 底部:一个区域,用来显示生成的图片或结果信息。
  • 侧边或底部:再加一个列表,用来展示生成历史记录。

具体操作如下:

  1. 从左侧的Widget Box里,拖一个Text Edit控件到窗口上部,作为我们的描述输入区。在右侧属性编辑器里,可以给它改个对象名,比如textEdit_Input,方便后面写代码时引用。还可以在placeholderText属性里输入提示文字,如“请输入对皮革连衣裙的描述...”。
  2. 拖一个Push Button到输入框下方,改个对象名叫pushButton_Generate,显示文本改成“生成”。
  3. 我们需要一个地方来显示图片。拖一个Label控件到按钮下方,拉大一些。这个Label默认是用来显示文字的,但也可以显示图片。改个对象名叫label_ImageDisplay,并把它的alignment属性设置为AlignCenter,让图片居中。清空它的text属性。
  4. 再拖一个List Widget控件到窗口右侧或label_ImageDisplay下方,用来做历史记录列表。改个对象名叫listWidget_History
  5. 最后,使用Vertical SpacerHorizontal Spacer(在Spacers类别里)来调整各个控件之间的间距,让布局看起来更舒服。你也可以使用Layouts(如Vertical Layout)来管理控件组,这样窗口缩放时,控件会自动调整大小。

设计完大概长这样(描述性文字):

[ 多行文本输入框:请输入对皮革连衣裙的描述... ] [ “生成”按钮 ] [ 图片显示区域 ] [ 历史记录列表:条目1, 条目2... ]

保存mainwindow.ui文件。Qt Creator 会自动将界面文件转换成 C++ 代码,我们接下来就要去写让这些控件“动起来”的逻辑。

3. 编写核心业务逻辑

界面是静态的,逻辑才是灵魂。我们需要在代码里做三件事:处理按钮点击、调用模型API、更新界面显示。

3.1 连接信号与槽

Qt 的核心机制之一就是“信号与槽”。简单理解,就是当某个事件发生(如按钮被点击,这是一个信号),自动触发一段执行代码(这是一个槽函数)。

我们打开Sources文件夹下的mainwindow.cpp文件。在MainWindow类的构造函数MainWindow::MainWindow(...)里,添加连接代码:

#include "mainwindow.h" #include "ui_mainwindow.h" #include <QNetworkAccessManager> #include <QNetworkReply> #include <QJsonDocument> #include <QJsonObject> #include <QJsonArray> // ... 其他可能需要的头文件 MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent) , ui(new Ui::MainWindow) { ui->setupUi(this); // 这行是自动生成的,用于加载我们设计的UI // 初始化网络管理器 networkManager = new QNetworkAccessManager(this); // 连接按钮的点击信号到我们自定义的槽函数 connect(ui->pushButton_Generate, &QPushButton::clicked, this, &MainWindow::onGenerateButtonClicked); // 连接历史记录列表的点击信号,用于查看历史项详情 connect(ui->listWidget_History, &QListWidget::itemClicked, this, &MainWindow::onHistoryItemClicked); }

同时,需要在mainwindow.h文件中声明这些槽函数和私有成员变量:

// mainwindow.h private slots: void onGenerateButtonClicked(); void onHistoryItemClicked(QListWidgetItem *item); private: Ui::MainWindow *ui; QNetworkAccessManager *networkManager; // 用于网络请求 // 可以添加一个列表或结构来存储更详细的历史数据 // QList<GenerationRecord> historyRecords; };

3.2 实现生成请求槽函数

当用户点击“生成”按钮时,onGenerateButtonClicked()函数就会被调用。在这里,我们要组装请求,发送给AI模型的API。

假设你的Leather Dress Collection模型服务运行在http://localhost:8000,有一个/generate的POST接口,接收JSON格式的请求,比如{"prompt": "描述文字"}

void MainWindow::onGenerateButtonClicked() { QString prompt = ui->textEdit_Input->toPlainText().trimmed(); if (prompt.isEmpty()) { // 简单提示用户输入不能为空 ui->label_ImageDisplay->setText("请输入描述文字。"); return; } // 1. 组装JSON请求体 QJsonObject json; json["prompt"] = prompt; // 可以根据模型API需要添加其他参数,如数量、尺寸等 // json["num_images"] = 1; // json["size"] = "512x512"; QJsonDocument doc(json); QByteArray data = doc.toJson(); // 2. 创建网络请求 QUrl url("http://localhost:8000/generate"); // 替换为你的模型API地址 QNetworkRequest request(url); request.setHeader(QNetworkRequest::ContentTypeHeader, "application/json"); // 3. 发送POST请求 QNetworkReply *reply = networkManager->post(request, data); // 4. 连接请求完成的信号 connect(reply, &QNetworkReply::finished, this, [this, reply, prompt]() { onGenerateRequestFinished(reply, prompt); }); // 可选:更新UI提示正在生成 ui->label_ImageDisplay->setText("正在生成,请稍候..."); ui->pushButton_Generate->setEnabled(false); // 防止重复点击 }

3.3 处理API响应并更新UI

请求完成后,无论成功失败,都会触发finished信号。我们在一个统一的函数里处理回复。

void MainWindow::onGenerateRequestFinished(QNetworkReply *reply, const QString &prompt) { // 恢复按钮状态 ui->pushButton_Generate->setEnabled(true); if (reply->error() != QNetworkReply::NoError) { // 处理网络错误 ui->label_ImageDisplay->setText("请求失败: " + reply->errorString()); reply->deleteLater(); return; } QByteArray responseData = reply->readAll(); reply->deleteLater(); // 重要:及时清理reply对象 QJsonParseError parseError; QJsonDocument jsonDoc = QJsonDocument::fromJson(responseData, &parseError); if (parseError.error != QJsonParseError::NoError || jsonDoc.isNull()) { ui->label_ImageDisplay->setText("解析响应失败。"); return; } QJsonObject jsonObj = jsonDoc.object(); // 假设成功响应包含一个 `image_url` 字段或直接是base64编码的图片数据 // 情况A:返回的是图片URL if (jsonObj.contains("image_url")) { QString imageUrl = jsonObj["image_url"].toString(); // 这里需要再发起一个网络请求下载图片,然后显示。 // 为了简化,我们假设另一种更直接的情况。 } // 情况B:返回的是base64编码的图片数据(更常见于原型/测试) if (jsonObj.contains("image_data")) { QString base64Data = jsonObj["image_data"].toString(); QByteArray imageData = QByteArray::fromBase64(base64Data.toUtf8()); QPixmap pixmap; if (pixmap.loadFromData(imageData)) { // 缩放图片以适应Label,同时保持比例 pixmap = pixmap.scaled(ui->label_ImageDisplay->size(), Qt::KeepAspectRatio, Qt::SmoothTransformation); ui->label_ImageDisplay->setPixmap(pixmap); ui->label_ImageDisplay->setText(""); // 清空可能的错误文本 // 添加到历史记录 addToHistory(prompt, pixmap); } else { ui->label_ImageDisplay->setText("加载图片数据失败。"); } } else { ui->label_ImageDisplay->setText("响应中未找到图片数据。"); } }

3.4 实现历史记录功能

历史记录功能让用户可以回顾之前的生成结果。我们可以简单地在列表里存储提示词,并关联内存中的图片(或图片路径)。

首先,添加一个辅助函数来将生成结果加入历史:

void MainWindow::addToHistory(const QString &prompt, const QPixmap &resultPixmap) { // 创建一个简短的条目文本(例如,提示词的前20个字符) QString shortPrompt = prompt.length() > 20 ? prompt.left(20) + "..." : prompt; QString timeStr = QDateTime::currentDateTime().toString("hh:mm:ss"); QString itemText = QString("[%1] %2").arg(timeStr).arg(shortPrompt); // 添加到ListWidget QListWidgetItem *newItem = new QListWidgetItem(itemText, ui->listWidget_History); // 我们可以将完整的提示词或图片数据存储在Item的UserRole中,以便点击时检索 // 这里简单存储提示词 newItem->setData(Qt::UserRole, prompt); // 在实际项目中,你可能需要将pixmap保存到文件,并存储文件路径 // 将新项目添加到列表顶部 ui->listWidget_History->insertItem(0, newItem); }

然后,实现点击历史项查看详情的槽函数:

void MainWindow::onHistoryItemClicked(QListWidgetItem *item) { if (!item) return; QString fullPrompt = item->data(Qt::UserRole).toString(); // 在实际应用中,这里应该根据存储的信息(如文件路径)重新加载并显示对应的图片 ui->textEdit_Input->setPlainText(fullPrompt); // 将历史提示词填回输入框 // 可以在这里添加重新显示对应图片的逻辑 // 例如:loadAndDisplayImage(associatedImagePath); }

4. 运行与测试

代码写得差不多了,是时候看看成果了。

  1. 确保你的Leather Dress Collection模型服务已经在后台运行(例如在localhost:8000)。
  2. 回到 Qt Creator,点击左下角的绿色三角按钮(或按Ctrl+R)编译并运行你的客户端。
  3. 程序启动后,在输入框里试着描述一件皮革连衣裙,比如:“一件黑色的亮面皮质连衣裙,修身剪裁,带有银色拉链装饰”。
  4. 点击“生成”按钮。如果一切顺利,你会看到状态提示,然后生成的图片(或结果)会显示在中间的区域内。
  5. 再生成几次,观察右侧的历史记录列表是否在更新。

如果遇到问题,比如图片不显示、网络错误,别慌。检查以下几点:

  • 模型服务地址:代码里的http://localhost:8000/generate是否正确?
  • API格式:你的模型API期望的JSON格式和返回的格式,是否和代码里写的一致?
  • 网络权限:如果是Windows,确保防火墙没有阻止你的Qt程序发起网络请求。
  • 控制台输出:Qt Creator 下方的Application Output窗口会打印程序运行时的日志和错误信息,这是排查问题的好地方。

5. 下一步可以做什么

一个基本的原型客户端已经完成了。如果你觉得意犹未尽,这里有几个方向可以让它变得更强大、更实用:

  • 美化界面:使用 Qt 的样式表(QSS)来改变控件的外观,比如颜色、字体、圆角,让它看起来更专业。
  • 参数调节:在界面上增加一些滑块(QSlider)、下拉框(QComboBox),让用户可以调整生成图片的尺寸、数量、风格强度等参数。
  • 图片管理:实现历史图片的本地保存、删除、导出功能。可以为每个历史条目关联一个本地图片文件。
  • 错误处理与用户反馈:添加更友好的错误提示,比如弹窗(QMessageBox),或者在请求时显示一个加载动画。
  • 多模型支持:改造一下,让它能通过配置切换不同的模型API地址和参数,变成一个通用的AI模型测试客户端。

获取更多AI镜像

想探索更多AI镜像和应用场景?访问 CSDN星图镜像广场,提供丰富的预置镜像,覆盖大模型推理、图像生成、视频生成、模型微调等多个领域,支持一键部署。

http://www.jsqmd.com/news/475746/

相关文章:

  • 向AI学习项目技能(三)
  • 2026“养虾”狂潮:当 OpenClaw 成为新生产力,我们该狂欢还是冷思考?
  • Gemini Embedding 2把多模态信息整合同一向量空间了,还需要多向量列吗?
  • 洛谷有感!!!!!
  • Dataset类的使用
  • Agent Skills(智能体技能)
  • LeetCode热题100(三)
  • JamTools实用指南:五大核心功能的使用技巧与最佳实践
  • 我没有那么多数据,​我需要马上学,我不要硬规则,​我可以逐步学习,​现在我边标边学
  • 一句话让 AI 获取并且读完巴菲特十年股东大会实录,自动生成投资分析框架——InfiniSynapse 做到了
  • 2026年威海GEO推广哪家强套餐价格大揭秘
  • 在vscode中可以使用阿里云coding plan吗?
  • 突破Minecraft物品堆叠限制:如何用3行代码实现资源管理效率提升300%?
  • 【数据结构与算法】1_python版 _算法概念
  • LCL三相并网逆变器:准PR比例谐振控制策略详解与仿真说明文件解析
  • 【AI模型参考】AI智能的核心概念
  • Flutter 工具 loc_checker 的鸿蒙化适配实战 - 精准统计代码行数、自动化度量鸿蒙项目效能、构建质量门禁基石
  • 3.13打卡day27
  • 计算机毕业设计 java 学生就业信息管理系统 Java+SpringBoot 学生就业信息服务平台 Web 版高校就业信息管理系统
  • 技术逆向英语|202602022
  • 关于keil编译器版本问题的解决办法
  • 清杉科技:从技术研发到商业化运营的全面突破
  • 3步解锁音乐自由:ncmdump让NCM格式转换不再复杂
  • Python基于flask-django家用电器家电销售商城售后服务管理系统的设计与实现
  • 3.1~3.8
  • 【程序源代码】快递运单对账工具(客户可定制版)
  • 微信小程序音乐播放器毕设效率优化实战:从冗余加载到秒级响应
  • 解决node-sass@4.14.1 Node Sass is no longer supported. Please use `sass` or `sass-embedded` instead
  • 单片机的工厂方法模式和桥接模式结合使用
  • 5步精通资源下载器:从网络资源嗅探到批量下载的全攻略