linux之ubuntu qt界面开发开发点菜系统

作者:RouDragon日期:2025/11/16

首先这篇博客主要讲解的是如何设计一个基于qt开发的点菜系统,这方面有很多内容会引用他人的文章需要继续学习他人的文章才会明白此文章是在讲解啥。

自制点菜系统视频链接

整体设计思路

在这里插入图片描述
这张图其实很详细的介绍了点菜系统需要的技术,在开发板方面,也就是服务器端,首先屏幕显示也是基于qt开发,所有你的ubuntu qt开发的时候就得设置好其编译器和环境基于开发板的,同时你还需要另一套环境进行直接在开发板上测试不需要反反复复的在开发板上重装。屏幕显示部分还需要首先设置一个登陆界面当客户端也就是ubuntu或者电脑登陆完成后发送消息给开发板,告诉其可以点菜了否则还在此等待。点菜界面部分也就是需要设置一个输入人数餐桌号的界面后确认后进行菜品的选择。点菜图片是需要到网上下载并选择你想要的菜品图片比如辣椒炒肉、水煮活鱼等。开发板作为服务器需要与客户端ubuntu连接通讯协议采用tcp协议。
在ubuntu方面也就是客户端,需要用到数据库sqlite存储数据防止代码中断后数据就删除了,登陆界面也是qt开发,客户端与服务器通讯采用tcp协议。


首先第一部分了解tcp协议

了解一个协议最好的方式就是跟随老师学习。

此部分主要工作为tcp协议在Linux ubuntu 上的实操,tcp协议的详细介绍内容请参考韦东山相关教程百问网韦东山嵌入式Linux应用开发入门实验班5-3tcp示例
第一部分实操,主要是跟着韦老师学习,其实操课程。

首先下载代码放到Ubuntu中

在这里插入图片描述
首先你得知道作为Ubuntu中打开的程序是不需要makefile以及生成ko文件的,也就是其实你这文件代码也可以在win11的vscode中用编译器编译运行。

client.c

1#include <sys/types.h>          /* See NOTES */
2#include <sys/socket.h>
3#include <string.h>
4#include <sys/socket.h>
5#include <netinet/in.h>
6#include <arpa/inet.h>
7#include <unistd.h>
8#include <stdio.h>
9
10/* socket
11 * connect
12 * send/recv
13 */
14
15#define SERVER_PORT 8888
16
17int main(int argc, char **argv)
18{
19	int iSocketClient;
20	struct sockaddr_in tSocketServerAddr;
21	
22	int iRet;
23	unsigned char ucSendBuf[1000];
24	int iSendLen;
25	int iRecvLen;
26
27	if (argc != 2)
28	{
29		printf("Usage:\n");
30		printf("%s <server_ip>\n", argv[0]);
31		return -1;
32	}
33	//  1.面向连接的TCP协议(SOCK_STREAM) 的Socket
34	iSocketClient = socket(AF_INET, SOCK_STREAM, 0);
35
36	tSocketServerAddr.sin_family      = AF_INET;
37	tSocketServerAddr.sin_port        = htons(SERVER_PORT);  /* host to net, short */
38 	//tSocketServerAddr.sin_addr.s_addr = INADDR_ANY;
39 	if (0 == inet_aton(argv[1], &tSocketServerAddr.sin_addr))
40 	{
41		printf("invalid server_ip\n");
42		return -1;
43	}
44	memset(tSocketServerAddr.sin_zero, 0, 8);
45
46	// 2.连接服务器,设置好的服务器地址发起TCP连接请求
47	iRet = connect(iSocketClient, (const struct sockaddr *)&tSocketServerAddr, sizeof(struct sockaddr));	
48	if (-1 == iRet)
49	{
50		printf("connect error!\n");
51		return -1;
52	}
53
54	while (1)
55	{
56		if (fgets(ucSendBuf, 999, stdin))
57		{   // 3.发送数据到服务器
58			iSendLen = send(iSocketClient, ucSendBuf, strlen(ucSendBuf), 0);
59			if (iSendLen <= 0)
60			{   // 4
61				close(iSocketClient);
62				return -1;
63			}
64			// 接收服务器的回复并打印
65			// recv函数等待并读取服务器返回的数据。这是一个阻塞调用
66			iRecvLen = recv(iSocketClient, ucSendBuf, 999, 0);
67			if (iRecvLen > 0)
68			{
69				ucSendBuf[iRecvLen] = '\0';
70				printf("From server: %s\n", ucSendBuf);
71			}	
72		}
73	}
74	
75	return 0;
76}
77
78

server.c

1#include <sys/types.h>          /* See NOTES */
2#include <sys/socket.h>
3#include <string.h>
4#include <sys/socket.h>
5#include <netinet/in.h>
6#include <arpa/inet.h>
7#include <unistd.h>
8#include <stdio.h>
9#include <signal.h>
10
11
12/* socket
13 * bind
14 * listen
15 * accept
16 * send/recv
17 */
18// 服务器监听的端口号(8888)
19// BACKLOG定义了连接请求队列的最大长度
20#define SERVER_PORT 8888
21#define BACKLOG     10
22
23int main(int argc, char **argv)
24{
25	int iSocketServer;
26	int iSocketClient;
27	struct sockaddr_in tSocketServerAddr;
28	struct sockaddr_in tSocketClientAddr;
29	int iRet;
30	int iAddrLen;
31	int cnt;
32
33	int iRecvLen;
34	unsigned char ucRecvBuf[1000];
35
36	int iClientNum = -1;
37
38	signal(SIGCHLD,SIG_IGN);
39	// 1.创建一个使用 IPv4地址族(AF_INET) 和 面向连接的TCP协议(SOCK_STREAM) 的Socket
40	iSocketServer = socket(AF_INET, SOCK_STREAM, 0);
41	if (-1 == iSocketServer)
42	{
43		printf("socket error!\n");
44		return -1;
45	}
46
47	tSocketServerAddr.sin_family      = AF_INET;
48	tSocketServerAddr.sin_port        = htons(SERVER_PORT);  /* host to net, short */
49 	tSocketServerAddr.sin_addr.s_addr = INADDR_ANY;
50	memset(tSocketServerAddr.sin_zero, 0, 8);
51	
52	// 2.bind函数将创建的Socket与指定的IP地址和端口号绑定
53	iRet = bind(iSocketServer, (const struct sockaddr *)&tSocketServerAddr, sizeof(struct sockaddr));
54	if (-1 == iRet)
55	{
56		printf("bind error!\n");
57		return -1;
58	}
59
60	// 3.服务器Socket开始监听来自客户端的连接请求
61	iRet = listen(iSocketServer, BACKLOG);
62	if (-1 == iRet)
63	{
64		printf("listen error!\n");
65		return -1;
66	}
67
68	while (1)
69	{
70		iAddrLen = sizeof(struct sockaddr);
71		// accept函数从连接请求队列中取出一个请求,为该连接创建一个新的Socket(iSocketClient)
72		// 4.并获取客户端的地址信息。这是一个阻塞调用,直到有连接请求才会返回
73		iSocketClient = accept(iSocketServer, (struct sockaddr *)&tSocketClientAddr, &iAddrLen);
74		
75		if (-1 != iSocketClient)  // 连接成功后,打印客户端信息
76		{
77			iClientNum++;
78			printf("Get connect from client %d : %s\n",  iClientNum, inet_ntoa(tSocketClientAddr.sin_addr));
79			if (!fork())
80			{
81				cnt = 0;
82				/* 子进程的源码 */
83				while (1)
84				{
85					/* 5.使用 recv函数读取客户端发送的数据 */
86					iRecvLen = recv(iSocketClient, ucRecvBuf, 999, 0);
87					if (iRecvLen <= 0)
88					{
89						close(iSocketClient);
90						return -1;
91					}
92					else
93					{
94						ucRecvBuf[iRecvLen] = '\0';
95						printf("Get Msg From Client %d: %s\n", iClientNum, ucRecvBuf);
96						sprintf(ucRecvBuf, "Get Msg cnt %d", cnt++);
97						// send函数向客户端发送一个带计数器的回应消息
98						send(iSocketClient, ucRecvBuf, strlen(ucRecvBuf), 0);
99					}
100				}				
101			}
102		}
103	}
104	// 6
105	close(iSocketServer);
106	return 0;
107}
108
109
1gcc -o server server.c 
2gcc -o client client.c
3./server
4./client 192.168.101.129
5

打开两个终端分别运行客户端、服务器端程序测试。
在这里插入图片描述
从图中可以看出,你得设置两个终端,一个做服务器,一个做客户端。设置ip时,可以任意指定其中的一个即可。



其次qt开发界面基础

这方面是基于Ubuntu 的qt开发的基础方面的知识。
首先安装ubuntu时我是跟着韦东山的此教程百问网韦东山嵌入式Linux应用开发入门实验班—编译烧录qt系统

跟着他的教程首先完成了最基础的实现,以上就不详细展开说了。
在这里插入图片描述
输入 chmod +x qt然后按一下 Tab键,终端会自动补全完整的文件名。
./qt-opensource-linux-x64-5.12.9.run

在学习的过程中我也遇到了一些问题,我的没有找到
在这里插入图片描述
在终端中的确没有找到此文件。
在这里插入图片描述

还有就是qt里面设置的slot最开始按的时候没反应,发现代码中文件名和设置的函数名得一模一样
在这里插入图片描述
如下图所示的设置。
在这里插入图片描述
以上就是我跟着他的时候出现的部分错误你看能不能帮你解决问题。

但是我们要明白,他编译的环境是针对开发板编译的都是32位的qmake也是win32位,如果想在ubuntu上测试会出现,以下这个错误。

102:23:09: Starting /home/book/QT_Project/build-server_jiemian-100ask_imx6ull-Debug/server_jiemian...
202:23:09: Failed to start program. Path or permissions wrong?
302:23:09: /home/book/QT_Project/build-server_jiemian-100ask_imx6ull-Debug/server_jiemian exited with code -1
402:23:09: The process failed to start. Either the invoked program "/home/book/QT_Project/build-server_jiemian-100ask_imx6ull-Debug/server_jiemian" is missing, or you may have insufficient permissions to invoke the program.
5

在这里插入图片描述
会发现miss找不到路径。Ubuntu上运行不了,但是下载到开发板上可以运行。
接下来你需要设置桌面版本也就是unbuntu版本。
在这里插入图片描述
到时候你想给开发板编译就选上面哪个,想在板子上运行就选下面这个。上面哪个C,C++编译器是32位的包括qt version也是。所以你如果要设置ubuntu的就得找到x86 64位的qmake 安装。

在这里插入图片描述
输入此命令更新库

1sudo apt-get update
2sudo apt-get install qt5-default
3

安装qmake
qmake --version查看版本,查看其安装路径,然后把路径放到Qt Version里面。保存Kits再新建一个。
在这里插入图片描述

在这里插入图片描述
然后编译后你的ubuntu就可以正常运行了。
在这里插入图片描述
你可以在debug处选择使用的编译器,等你在ubuntu上调好后就可以导入到开发板上直接使用了。

本人第一个qt界面是参考的这位博主的文章

Qt设计精美的登录注册界面(包含SQLite数据库应用)
具体详细步骤可以跟着他的来。

在这里插入图片描述

这也就是我在ubuintu上设计的第一个界面。

在这里插入图片描述
ui界面设计的时候选择这个将他的代码复制进去。
在这里插入图片描述
在这里插入图片描述

升级后的界面。 但在这个过程中我发现,我一直输入不了中文,后来才知道得安装qt支持的中文包。
安装Qt5的Fcitx前端插件:
在终端中执行以下命令:

1sudo apt install fcitx-frontend-qt5
2

安装后,文件通常在这里:
你可以用 ls命令检查一下是否存在:

1/usr/lib/x86_64-linux-gnu/qt5/plugins/platforminputcontexts/libfcitxplatforminputcontextplugin.so
2ls /usr/lib/x86_64-linux-gnu/qt5/plugins/platforminputcontexts/libfcitxplatforminputcontextplugin.so
3

将插件文件复制到Qt Creator的插件目录(这是解决问题的核心操作)
首先,需要找到您Qt Creator的安装路径。​ 如果您是通过Qt官方安装程序安装的,路径通常像这样:
/opt/Qt/Tools/QtCreator/lib/Qt/plugins/platforminputcontexts/
但是我的在:
/home/book/Qt5.12.9/Tools/QtCreator/lib/Qt/plugins/platforminputcontexts/
然后,使用cp命令复制文件(请将下面的路径替换为您电脑上真实的Qt安装路径):

1sudo cp /usr/lib/x86_64-linux-gnu/qt5/plugins/platforminputcontexts/libfcitxplatforminputcontextplugin.so /home/book/Qt5.12.9/Tools/QtCreator/lib/Qt/plugins/platforminputcontexts/
2

在这里插入图片描述
在这里插入图片描述
ctrl+空格就可以输入中文了

后续内容就是加载数据库,到时候和开发板数据相关联。

在这里插入图片描述
在这里插入图片描述

最后实现的登陆界面

详细代码主要涉及到注册界面、登陆界面。代码放在最后的链接中。

接下来就要涉及到点菜系统的整个开发了,客户端登陆可以直接使用以上界面。所以关键就是服务器端的点菜了。

首先我的mainwindow计划实现一个等待消息的界面,通过tcp协议接受begin_val后进入点菜界面的跳转。

mainwindow.h

1#ifndef MAINWINDOW_H
2#define MAINWINDOW_H
3
4#include <QMainWindow>
5#include <QTcpServer>
6#include <QTcpSocket>
7class desk_people_num;
8QT_BEGIN_NAMESPACE
9namespace Ui { class MainWindow; }
10QT_END_NAMESPACE
11
12class MainWindow : public QMainWindow
13{
14    Q_OBJECT
15
16public:
17    MainWindow(QWidget *parent = nullptr);
18    ~MainWindow();
19
20private slots:
21    void onNewConnection();           // 处理新连接
22    void onReadyRead();               // 处理接收数据
23    void onSocketError(QAbstractSocket::SocketError error); // 处理socket错误
24
25private:
26    Ui::MainWindow *ui;
27    QTcpServer *tcpServer;           // TCP服务器
28    QTcpSocket *clientSocket;        // 客户端socket
29    desk_people_num *deskPeopleWindow; // 第二个界面指针
30    void setupTCPConnection();       // 设置TCP连接
31    void switchToDeskPeopleNum();    // 切换到第二个界面
32    void handleOrder();
33
34public:
35    QTcpSocket* getClientSocket() const { return clientSocket; }
36    void sendResponseToClient(const QString &response);
37};
38
39// 全局变量声明
40extern QTcpSocket* clientSocket;
41extern desk_people_num* deskPeopleWindow;
42#endif // MAINWINDOW_H
43
44

mainwindow.cpp

1#include "mainwindow.h"
2#include "ui_mainwindow.h"
3#include <QGraphicsDropShadowEffect>
4#include <QMessageBox>
5#include <QDebug>
6#include "desk_people_num.h"
7#include "ui_desk_people_num.h"
8
9// 定义全局变量
10QTcpSocket* clientSocket = nullptr;  //初始化为nullptr
11desk_people_num* deskPeopleWindow= nullptr;
12MainWindow::MainWindow(QWidget *parent)
13    : QMainWindow(parent)
14    , ui(new Ui::MainWindow)
15    , tcpServer(nullptr)
16    , clientSocket(nullptr)
17    , deskPeopleWindow(nullptr)
18{
19    ui->setupUi(this);
20    //设置图片
21    QPixmap *pix = new QPixmap(":/new/prefix1/diancai.jpg");
22    QSize sz = ui->label_image->size();
23    ui->label_image->setPixmap(pix->scaled(sz));
24
25    //设置图片阴影效果
26    QGraphicsDropShadowEffect *shadow = new QGraphicsDropShadowEffect(this);
27    shadow->setOffset(-3, 0);
28    shadow->setColor(QColor("#888888"));
29    shadow->setBlurRadius(30);
30    ui->label_image->setGraphicsEffect(shadow);
31
32    // 设置TCP连接
33    setupTCPConnection();
34}
35
36void MainWindow::setupTCPConnection()
37{
38    // 创建TCP服务器
39    tcpServer = new QTcpServer(this);
40
41    // 监听所有IP的8080端口(您可以根据需要修改端口号)
42    //if (!tcpServer->listen(QHostAddress::Any, 8080)) {
43    if (!tcpServer->listen(QHostAddress("192.168.101.129"), 8080)) {
44        QMessageBox::critical(this, "TCP Server",
45                             QString("无法启动服务器: %1").arg(tcpServer->errorString()));
46        return;
47    }
48
49    // 连接新连接信号
50    connect(tcpServer, &QTcpServer::newConnection, this, &MainWindow::onNewConnection);
51
52    qDebug() << "TCP服务器已启动,监听端口: 8080";
53}
54
55void MainWindow::onNewConnection()
56{
57    // 如果有已连接的客户端,先断开
58    if (clientSocket) {
59        clientSocket->disconnectFromHost();
60        clientSocket->deleteLater();
61        clientSocket = nullptr;
62        ::clientSocket = nullptr; // 同步全局变量
63    }
64
65    // 获取新连接
66    clientSocket = tcpServer->nextPendingConnection();
67    ::clientSocket = clientSocket; // 同步到全局变量
68
69    // 连接信号槽
70    connect(clientSocket, &QTcpSocket::readyRead, this, &MainWindow::onReadyRead);
71    connect(clientSocket, QOverload<QAbstractSocket::SocketError>::of(&QTcpSocket::error),
72            this, &MainWindow::onSocketError);
73
74    qDebug() << "新的客户端连接:" << clientSocket->peerAddress().toString();
75    qDebug() << "全局clientSocket地址:" << ::clientSocket;
76    qDebug() << "成员clientSocket地址:" << clientSocket;
77}
78
79//static int begin_val=0;
80void MainWindow::onReadyRead()
81{
82    if (!clientSocket) return;
83
84    // 读取所有数据
85    QByteArray data = clientSocket->readAll();
86    QString message = QString::fromUtf8(data).trimmed();
87
88    qDebug() << "接收到消息:" << message;
89
90    // 检查是否为开始消息
91    if (message == "begin_val") {
92        // 向客户端发送"ok"响应
93        sendResponseToClient("ok");
94        qDebug() << "接收到开始消息,准备切换界面";
95        switchToDeskPeopleNum();
96    }
97}
98
99// 向客户端发送响应
100void MainWindow::sendResponseToClient(const QString &response)
101{
102    if (clientSocket && clientSocket->state() == QAbstractSocket::ConnectedState) {
103        QByteArray responseData = response.toUtf8();
104        qint64 bytesWritten = clientSocket->write(responseData);
105
106        if (bytesWritten == -1) {
107            qDebug() << "发送响应失败:" << clientSocket->errorString();
108        } else {
109            // 确保数据被发送
110            clientSocket->flush();
111            qDebug() << "已向客户端发送响应:" << response;
112        }
113    } else {
114        qDebug() << "客户端未连接,无法发送响应";
115    }
116}
117
118void MainWindow::onSocketError(QAbstractSocket::SocketError error)
119{
120    Q_UNUSED(error)
121    if (clientSocket) {
122        qDebug() << "Socket错误:" << clientSocket->errorString();
123    }
124}
125
126void MainWindow::switchToDeskPeopleNum()
127{
128    //this->close();  // 关界面
129    this->hide();  // 改为隐藏而不是关闭
130    desk_people_num *s = new desk_people_num;  //跳至singup界面
131    s->show();
132
133    qDebug() << "已切换到desk_people_num界面";
134}
135
136MainWindow::~MainWindow()
137{
138    if (tcpServer) {
139        tcpServer->close();
140    }
141    if (clientSocket) {
142        clientSocket->close();
143    }
144    delete ui;
145}
146
147// 在MainWindow的成员函数中
148extern int g_deskNumber,g_peopleNumber;
149void MainWindow::handleOrder()
150{
151    // 可以直接访问全局变量
152    if (g_deskNumber > 0 && g_peopleNumber > 0) {
153        qDebug() << "桌号:" << g_deskNumber << "人数:" << g_peopleNumber;
154
155        // 发送到服务器或其他处理
156        QString orderInfo = QString("桌号:%1,人数:%2").arg(g_deskNumber).arg(g_peopleNumber);
157        //sendToServer(orderInfo);
158
159        // 重置选择(可选)
160        // g_deskNumber = 0;
161        // g_peopleNumber = 0;
162    } else {
163        qDebug() << "请先选择桌号和人数";
164    }
165}
166
167

在这里插入图片描述
如图所示以上代码实现的就是这个界面。
在这里插入图片描述
同时我会开启tcp监听,当有连接后并发送消息给ubuntu服务器端时,向客户端返回消息ok。
在这里插入图片描述
我是通过正点原子的调试助手模拟发送。
完成以上部分后开始计划desk_people_num选桌号选人数的界面设计,当选好人数和桌号后按下确定跳转界面,当按下取消后界面数据清空重新选择。

在这里插入图片描述

desk_people_num.h

1#ifndef DESK_PEOPLE_NUM_H
2#define DESK_PEOPLE_NUM_H
3
4#include <QWidget>
5#include <QDebug>
6#include "xuancai.h"
7namespace Ui {
8class desk_people_num;
9}
10
11class desk_people_num : public QWidget
12{
13    Q_OBJECT
14
15public:
16    explicit desk_people_num(QWidget *parent = nullptr);
17    ~desk_people_num();
18
19private slots:
20
21
22    void on_desk1_Button_clicked();
23
24    void on_desk2_Button_clicked();
25
26    void on_desk3_Button_clicked();
27
28    void on_desk4_Button_clicked();
29
30    void on_desk5_Button_clicked();
31
32    void on_desk6_Button_clicked();
33
34    void on_desk7_Button_clicked();
35
36    void on_desk8_Button_clicked();
37
38    void on_desk9_Button_clicked();
39
40    void on_desk10_Button_clicked();
41
42    void on_people1_Button_clicked();
43
44    void on_people2_Button_clicked();
45
46    void on_people3_Button_clicked();
47
48    void on_people4_Button_clicked();
49
50    void on_people5_Button_clicked();
51
52    void on_people6_Button_clicked();
53
54    void on_people7_Button_clicked();
55
56    void on_people8_Button_clicked();
57
58    void on_people9_Button_clicked();
59
60    void on_ensureButton_clicked();
61
62    void on_cancelButton_clicked();
63
64private:
65    Ui::desk_people_num *ui;
66    // 当前选择的桌号和人数
67    int currentDeskNumber;
68    int currentPeopleNumber;
69
70    // 更新按钮样式
71    void updateDeskButtonsStyle();
72    void updatePeopleButtonsStyle();
73    void resetAllSelection();
74};
75
76#endif // DESK_PEOPLE_NUM_H
77
78

desk_people_num.cpp

1#include "desk_people_num.h"
2#include "ui_desk_people_num.h"
3#include "xuancai.h"
4// 定义全局变量
5int g_deskNumber = 0;        // 初始值为0,表示未选择
6int g_peopleNumber = 0;      // 初始值为0,表示未选择
7
8desk_people_num::desk_people_num(QWidget *parent) :
9    QWidget(parent),
10    ui(new Ui::desk_people_num)
11{
12    ui->setupUi(this);
13    // 初始化全局变量
14    g_deskNumber = 0;
15    g_peopleNumber = 0;
16}
17
18
19desk_people_num::~desk_people_num()
20{
21    delete ui;
22}
23
24
25void desk_people_num::updateDeskButtonsStyle()
26{
27    // 重置所有桌号按钮样式
28    QList<QPushButton*> deskButtons = {
29        ui->desk1_Button, ui->desk2_Button, ui->desk3_Button,
30        ui->desk4_Button, ui->desk5_Button, ui->desk6_Button,
31        ui->desk7_Button, ui->desk8_Button, ui->desk9_Button,
32        ui->desk10_Button
33    };
34
35    for (int i = 0; i < deskButtons.size(); ++i) {
36        if ((i + 1) == currentDeskNumber) {
37            // 选中的按钮样式 - 绿色背景
38            deskButtons[i]->setStyleSheet(
39                "QPushButton {"
40                "   background-color: #4CAF50;"
41                "   color: white;"
42                "   border: 2px solid #45a049;"
43                "   border-radius: 5px;"
44                "   font-weight: bold;"
45                "}"
46                "QPushButton:hover {"
47                "   background-color: #45a049;"
48                "}"
49            );
50        } else {
51            // 未选中的按钮样式 - 灰色背景
52            deskButtons[i]->setStyleSheet(
53                "QPushButton {"
54                "   background-color: #f0f0f0;"
55                "   color: #333333;"
56                "   border: 1px solid #cccccc;"
57                "   border-radius: 5px;"
58                "}"
59                "QPushButton:hover {"
60                "   background-color: #e0e0e0;"
61                "}"
62            );
63        }
64    }
65}
66
67void desk_people_num::updatePeopleButtonsStyle()
68{
69    // 重置所有人数按钮样式
70    QList<QPushButton*> peopleButtons = {
71        ui->people1_Button, ui->people2_Button, ui->people3_Button,
72        ui->people4_Button, ui->people5_Button, ui->people6_Button,
73        ui->people7_Button, ui->people8_Button, ui->people9_Button
74    };
75
76    for (int i = 0; i < peopleButtons.size(); ++i) {
77        if ((i + 1) == currentPeopleNumber) {
78            // 选中的按钮样式 - 蓝色背景
79            peopleButtons[i]->setStyleSheet(
80                "QPushButton {"
81                "   background-color: #2196F3;"
82                "   color: white;"
83                "   border: 2px solid #0b7dda;"
84                "   border-radius: 5px;"
85                "   font-weight: bold;"
86                "}"
87                "QPushButton:hover {"
88                "   background-color: #0b7dda;"
89                "}"
90            );
91        } else {
92            // 未选中的按钮样式 - 灰色背景
93            peopleButtons[i]->setStyleSheet(
94                "QPushButton {"
95                "   background-color: #f0f0f0;"
96                "   color: #333333;"
97                "   border: 1px solid #cccccc;"
98                "   border-radius: 5px;"
99                "}"
100                "QPushButton:hover {"
101                "   background-color: #e0e0e0;"
102                "}"
103            );
104        }
105    }
106}
107
108// 重置所有选择
109void desk_people_num::resetAllSelection()
110{
111    currentDeskNumber = 0;
112    currentPeopleNumber = 0;
113    g_deskNumber = 0;
114    g_peopleNumber = 0;
115
116    updateDeskButtonsStyle();
117    updatePeopleButtonsStyle();
118
119    qDebug() << "已重置所有选择: 桌号 =" << g_deskNumber << "人数 =" << g_peopleNumber;
120}
121
122void desk_people_num::on_desk1_Button_clicked()
123{
124    currentDeskNumber = 1; g_deskNumber = 1;
125    updateDeskButtonsStyle();
126    qDebug() << "选择桌号:" << g_deskNumber;
127}
128
129void desk_people_num::on_desk2_Button_clicked()
130{
131    currentDeskNumber = 2; g_deskNumber = 2;
132    updateDeskButtonsStyle();
133    qDebug() << "选择桌号:" << g_deskNumber;
134}
135
136void desk_people_num::on_desk3_Button_clicked()
137{
138    currentDeskNumber = 3; g_deskNumber = 3;
139    updateDeskButtonsStyle();
140    qDebug() << "选择桌号:" << g_deskNumber;
141}
142
143void desk_people_num::on_desk4_Button_clicked()
144{
145     currentDeskNumber = 4; g_deskNumber = 4;
146     updateDeskButtonsStyle();
147     qDebug() << "选择桌号:" << g_deskNumber;
148}
149
150void desk_people_num::on_desk5_Button_clicked()
151{
152    currentDeskNumber = 5; g_deskNumber = 5;
153    updateDeskButtonsStyle();
154    qDebug() << "选择桌号:" << g_deskNumber;
155}
156
157void desk_people_num::on_desk6_Button_clicked()
158{
159    currentDeskNumber = 6; g_deskNumber = 6;
160    updateDeskButtonsStyle();
161    qDebug() << "选择桌号:" << g_deskNumber;
162}
163
164void desk_people_num::on_desk7_Button_clicked()
165{
166    currentDeskNumber = 7; g_deskNumber = 7;
167    updateDeskButtonsStyle();
168    qDebug() << "选择桌号:" << g_deskNumber;
169}
170
171void desk_people_num::on_desk8_Button_clicked()
172{
173     currentDeskNumber = 8; g_deskNumber = 8;
174     updateDeskButtonsStyle();
175     qDebug() << "选择桌号:" << g_deskNumber;
176}
177
178void desk_people_num::on_desk9_Button_clicked()
179{
180    currentDeskNumber = 9; g_deskNumber = 9;
181    updateDeskButtonsStyle();
182    qDebug() << "选择桌号:" << g_deskNumber;
183}
184
185void desk_people_num::on_desk10_Button_clicked()
186{
187    currentDeskNumber = 10; g_deskNumber = 10;
188    updateDeskButtonsStyle();
189    qDebug() << "选择桌号:" << g_deskNumber;
190}
191
192void desk_people_num::on_people1_Button_clicked()
193{
194    currentPeopleNumber = 1; g_peopleNumber = 1;
195    updatePeopleButtonsStyle();
196    qDebug() << "选择人数:" << g_peopleNumber;
197}
198
199void desk_people_num::on_people2_Button_clicked()
200{
201    currentPeopleNumber = 2; g_peopleNumber = 2;
202    updatePeopleButtonsStyle();
203    qDebug() << "选择人数:" << g_peopleNumber;
204}
205
206void desk_people_num::on_people3_Button_clicked()
207{
208    currentPeopleNumber = 3; g_peopleNumber = 3;
209    updatePeopleButtonsStyle();
210    qDebug() << "选择人数:" << g_peopleNumber;
211}
212
213void desk_people_num::on_people4_Button_clicked()
214{
215    currentPeopleNumber = 4; g_peopleNumber = 4;
216    updatePeopleButtonsStyle();
217    qDebug() << "选择人数:" << g_peopleNumber;
218}
219
220void desk_people_num::on_people5_Button_clicked()
221{
222     currentPeopleNumber = 5; g_peopleNumber = 5;
223     updatePeopleButtonsStyle();
224     qDebug() << "选择人数:" << g_peopleNumber;
225}
226
227void desk_people_num::on_people6_Button_clicked()
228{
229    currentPeopleNumber = 6; g_peopleNumber = 6;
230    updatePeopleButtonsStyle();
231    qDebug() << "选择人数:" << g_peopleNumber;
232}
233
234void desk_people_num::on_people7_Button_clicked()
235{
236    currentPeopleNumber = 7; g_peopleNumber = 7;
237    updatePeopleButtonsStyle();
238    qDebug() << "选择人数:" << g_peopleNumber;
239}
240
241void desk_people_num::on_people8_Button_clicked()
242{
243    currentPeopleNumber = 8; g_peopleNumber = 8;
244    updatePeopleButtonsStyle();
245    qDebug() << "选择人数:" << g_peopleNumber;
246}
247
248void desk_people_num::on_people9_Button_clicked()
249{
250    currentPeopleNumber = 9; g_peopleNumber = 9;
251    updatePeopleButtonsStyle();
252    qDebug() << "选择人数:" << g_peopleNumber;
253}
254
255void desk_people_num::on_ensureButton_clicked()
256{
257   // 检查是否已选择桌号和人数
258    if (g_deskNumber == 0 || g_peopleNumber == 0) {
259        qDebug() << "请先选择桌号和人数";
260        return;
261    }
262
263    qDebug() << "确定 - 桌号:" << g_deskNumber << "人数:" << g_peopleNumber;
264    //this->close();  // 关界面
265    this->hide();  // 改为隐藏而不是关闭
266    xuancai *s = new xuancai;  //跳至xuancai界面
267    s->show();
268    qDebug() << "已切换到xuancai界面";
269}
270
271void desk_people_num::on_cancelButton_clicked()
272{
273    // 重置所有选择
274    resetAllSelection();
275    qDebug() << "取消 - 已清空所有选择";
276}
277
278

在这里插入图片描述
实现的界面效果以及代码如上。

第3部分也就是选菜界面了,直接上效果图,那个test按钮主要是用来发送测试tcp协议连接的。
在这里插入图片描述

xuancai.h

1#ifndef XUANCAI_H
2#define XUANCAI_H
3
4#include <QWidget>
5#include "mainwindow.h"
6namespace Ui {
7class xuancai;
8}
9
10class xuancai : public QWidget
11{
12    Q_OBJECT
13
14public:
15    explicit xuancai(QWidget *parent = nullptr);
16    explicit xuancai(MainWindow* mainWindow, QWidget *parent = nullptr); // 传入MainWindow指针
17    ~xuancai();
18
19private slots:
20    void on_feiniu_Button1_clicked();
21
22    void on_feiniu_Button2_clicked();
23
24    void on_fish_Button1_clicked();
25
26    void on_fish_Button2_clicked();
27
28    void on_xia_Button1_clicked();
29
30    void on_xia_Button2_clicked();
31
32    void on_doufu_Button1_clicked();
33
34    void on_doufu_Button2_clicked();
35
36    void on_ensureButton_clicked();
37
38    void on_cancelButton_clicked();
39    void on_testConnectionButton_clicked();
40private:
41    int beefCount = 0;    // 肥牛卷数量
42    int fishCount = 0;    // 酸菜鱼数量
43    int xiaCount = 0;     // 盐焗大虾数量
44    int doufuCount = 0;    // 麻婆豆腐数量
45
46    // 重置所有菜品数量
47    void resetAllDishes();
48
49    // 发送数据到TCP服务器
50    void sendOrderToClient();  // 修改函数名,更清晰
51
52private:
53    Ui::xuancai *ui;
54
55};
56
57#endif // XUANCAI_H
58
59

xuancai.cpp

1#include "xuancai.h"
2#include "ui_xuancai.h"
3#include <QTcpSocket>
4#include <QMessageBox>
5#include <QJsonObject>
6#include <QJsonDocument>
7
8xuancai::xuancai(QWidget *parent) :
9    QWidget(parent),
10    ui(new Ui::xuancai),
11    beefCount(0),
12    fishCount(0),
13    xiaCount(0),
14    doufuCount(0)
15{
16    ui->setupUi(this);
17
18    // 初始化界面显示
19    ui->beef_label->setText("0");
20    ui->fish_label->setText("0");
21    ui->xia_label->setText("0");
22    ui->doufu_label->setText("0");
23
24    qDebug() << "选菜界面初始化完成";
25}
26
27xuancai::~xuancai()
28{
29    delete ui;
30}
31
32void xuancai::resetAllDishes()
33{
34    beefCount = 0;
35    fishCount = 0;
36    xiaCount = 0;
37    doufuCount = 0;
38
39    ui->beef_label->setText("0");
40    ui->fish_label->setText("0");
41    ui->xia_label->setText("0");
42    ui->doufu_label->setText("0");
43
44    qDebug() << "所有菜品数量已重置";
45}
46
47// 模仿MainWindow的sendResponseToClient函数
48void xuancai::sendOrderToClient()
49{
50    // 使用MainWindow中已建立的clientSocket
51    if (clientSocket && clientSocket->state() == QAbstractSocket::ConnectedState) {
52
53        // 创建JSON数据
54        QJsonObject jsonData;
55        jsonData["beef"] = beefCount;
56        jsonData["doufu"] = doufuCount;
57        jsonData["fish"] = fishCount;
58        jsonData["xia"] = xiaCount;
59
60        QJsonDocument doc(jsonData);
61        QByteArray orderData = doc.toJson(QJsonDocument::Compact);
62
63        qint64 bytesWritten = clientSocket->write(orderData);
64
65        if (bytesWritten == -1) {
66            qDebug() << "发送订单失败:" << clientSocket->errorString();
67            QMessageBox::warning(this, "发送错误", "订单发送失败");
68        } else {
69            // 确保数据被发送
70            clientSocket->flush();
71            qDebug() << "已向客户端发送订单,字节数:" << bytesWritten;
72            qDebug() << "发送的订单数据:" << orderData;
73            QMessageBox::information(this, "成功", "菜品已提交到客户端");
74        }
75    } else {
76        qDebug() << "客户端未连接,无法发送订单";
77        QMessageBox::warning(this, "连接错误", "客户端未连接,请先建立连接");
78    }
79}
80
81// 测试连接状态
82
83void xuancai::on_testConnectionButton_clicked()
84{
85    qDebug() << "=== 开始TCP连接测试 ===";
86
87    if (clientSocket && clientSocket->state() == QAbstractSocket::ConnectedState) {
88        qDebug() << "TCP连接状态: 已连接";
89        QMessageBox::information(this, "连接测试", "TCP连接测试成功!客户端已连接");
90    } else {
91        qDebug() << "TCP连接状态: 未连接";
92        QMessageBox::critical(this, "连接测试", "TCP连接测试失败!客户端未连接");
93    }
94
95    qDebug() << "=== TCP连接测试结束 ===";
96}
97
98void xuancai::on_ensureButton_clicked()
99{
100    if (beefCount == 0 && fishCount == 0 && xiaCount == 0 && doufuCount == 0) {
101        QMessageBox::information(this, "提示", "请至少选择一种菜品");
102        return;
103    }
104
105    qDebug() << "=== 选择的菜品 ===";
106    qDebug() << "牛肉:" << beefCount << "鱼肉:" << fishCount
107             << "虾:" << xiaCount << "豆腐:" << doufuCount;
108
109    // 使用MainWindow的客户端连接发送数据
110    sendOrderToClient();
111}
112
113void xuancai::on_cancelButton_clicked()
114{
115    resetAllDishes();
116}
117
118// 菜品数量增减按钮(保持不变)
119void xuancai::on_feiniu_Button2_clicked()
120{
121    beefCount++;
122    ui->beef_label->setText(QString::number(beefCount));
123}
124
125void xuancai::on_fish_Button2_clicked()
126{
127    fishCount++;
128    ui->fish_label->setText(QString::number(fishCount));
129}
130
131void xuancai::on_xia_Button2_clicked()
132{
133    xiaCount++;
134    ui->xia_label->setText(QString::number(xiaCount));
135}
136
137void xuancai::on_doufu_Button2_clicked()
138{
139    doufuCount++;
140    ui->doufu_label->setText(QString::number(doufuCount));
141}
142
143void xuancai::on_feiniu_Button1_clicked()
144{
145    if(beefCount > 0) {
146        beefCount--;
147        ui->beef_label->setText(QString::number(beefCount));
148    }
149}
150
151void xuancai::on_fish_Button1_clicked()
152{
153    if(fishCount > 0) {
154        fishCount--;
155        ui->fish_label->setText(QString::number(fishCount));
156    }
157}
158
159void xuancai::on_xia_Button1_clicked()
160{
161    if(xiaCount > 0) {
162        xiaCount--;
163        ui->xia_label->setText(QString::number(xiaCount));
164    }
165}
166
167void xuancai::on_doufu_Button1_clicked()
168{
169    if(doufuCount > 0) {
170        doufuCount--;
171        ui->doufu_label->setText(QString::number(doufuCount));
172    }
173}
174
175

在这里插入图片描述
最后的测试效果和代码如图所示,构建tcp类的时候注意用全局变量,不然单个页面完成后它会销毁断开连接,这个问题卡了我挺久的。

确保你的网络连接没问题后再在开发板上测试。
在这里插入图片描述

在这里插入图片描述

在这里插入图片描述
unbuntu_jiemian就是那个登陆注册的界面。diancai_system_imx6ull就是点菜系统界面。

通过网盘分享的文件:diancai_system_imx6ull.zip等2个文件
链接: https://pan.baidu.com/s/1SDu6y3SeMCb-EzpvP3hNPw?pwd=k4u4 提取码: k4u4


linux之ubuntu qt界面开发开发点菜系统》 是转载文章,点击查看原文


相关推荐


进入职场第五课——突破和跃升
Mapbarfront2025/11/14

观察、融入、立足、产出,度过这4个阶段之后,你已经稳稳地,成为团队里的主力输出了,接下来,如果你想从团队中的好员工,跃升为老板眼中的关键人物,从业务骨干到真正的团队核心,必须要做的下一步就是突破,易经乾卦中的或跃在渊,说的就是这个意思。 或是或许,代表着不确定性,跃是跳跃,代表着勇敢一搏,在渊是指在深渊里,代表着突破前在深渊里的等待,这个阶段,是你在积蓄了足够的力量之后,遇到合适的机会纵身一跃的时刻,这是审慎的冒险,也是耐心等待之后的水到渠成,想要完成这次关键的进阶,以下这5个动作,你要步步为营


uos基础 dmesg 查看内核的实时日志
行初心2025/11/13

统信桌面操作系统专业版V20(1070) Linux uos 5.10.97-arm64-desktop uos基础 dmesg 查看内核的实时日志 root@uos:~# dmesg -wH [11月10 14:59] [pid:3256,cpu1,Xwayland,1][HISI_DRM_HEAPS D]:do_alloc_memory: need alloc size=0x3000, now pool size=0x1a60000 [ +0.000000] [pid:3256,cpu1


苹果上线App Store Web版本,以后浏览外区更方便了
CocoaKier2025/11/12

近期,苹果低调上线了网页版 App Store(apps.apple.com/cn) 只要打开浏览器,用户就可以浏览AppStore了,即便非苹果设备也能访问,但目前只能浏览、搜索,不支持在网页端下载 app。 网页版的一个亮点是支持快速切换区域,我们只需修改网页地址中的区域代码即可快速浏览其他地区的 App Store 内容。这对于竞品分析,特别是出海产品的竞品分析,带来了非常大的便利,可以更方便快捷地查看某个国家地区的榜单,同类型应用有哪些,某个应用在不同地区的可用性、价格、评分、评论情况。


Day 7:05. 基于Nuxt开发博客项目-首页开发
申阳2025/11/10

一、前言 首页是站点的“脸面”,也是信息传达最直接的窗口。首页的设计质量,不仅关系到用户对站点的第一印象,更直接影响其使用体验与整体评价。因此,精心打造首页,至关重要。 我其实比较反感一些花里胡哨的页面,但是恰到好处的动画确实可以提高用户的体验,也利于网站推广。 我的目标是寻求平衡,信息作为主导,动画作为辅助。 下面开始我们的首页打造吧。 二、渐变文字标题 在tailwindcss的加持下,实现这种效果太方便了,只需要以下几个指令即可 <span class="ml-1 font-bold t


猿族代码战记:Mutex 升级版——守护 Swift 并发的“香蕉仓库”
大熊猫侯佩2025/11/8

🦍 引子 旧金山废墟的猿族技术区,金属支架撑起的荧光屏泛着冷光,首席 Swift 架构师科巴的指节因攥紧终端而发白 —— 食物计数系统又出问题了。 刚录入的 27 根香蕉,刷新页面竟变成 29,再点一下又跳回 28,旁边年轻猿工程师紧张地挠着头:“科巴大人,不会是小猩猩偷偷改数据吧?” 科巴瞪了他一眼:“是‘并发幽灵’!自从用 Actor 保护状态,简单的计数全成了麻烦 —— 查个库存要写await,就像咱们去仓库拿根香蕉,得先找凯撒签字、找后勤登记,折腾半小时!” 在本堂猩猩课堂中,您将学


保安公司的办理流程
2501_915837932025/11/5

北京保安公司还能新注册吗 哪里还能新注册保安公司 保安公司的收购流程与转让 保安公司转让信息与流程 一、保安公司注册核心要求与地区动态 全国统一基础标准根据《保安服务管理条例》及 2025 年最新执行细则,保安公司注册需满足: 1保安公司的人员资质:法人及至少 2 名高管必须持有二级保安师证书,且需提供无犯罪记录证明(含近 5 年无酒驾等行政违法记录)。退伍军人或有 25 年公安从业经历者,可凭相关证明免试获取报考资格。 2场地资金:商用办公地址面积因地区而异(北京 400㎡、武汉


批量转双层PDF(可识别各种语言) 中文绿色版
非凡ghost2025/10/31

批量转双层PDF软件是一种专门用于将单层图像PDF文件转换为包含文本层和图像层的双层PDF文件的工具。这种类型的PDF不仅保留了原始文档的外观,还增加了对文档内容进行搜索和选择的功能,极大地提高了文档管理和信息检索的效率。 软件功能 1. 批量转换:支持一次性导入多个PDF文件进行转换处理,极大提高工作效率。 2. OCR识别:利用光学字符识别技术,自动分析图像中的文字,并创建可选、可搜索的文本层。 3. 格式兼容性:可以处理多种格式的输入文件,包括但不限于PDF、JPEG、PNG等


Redis(90)如何配置Redis的身份验证?
Victor3562025/10/29

配置Redis的身份验证是保护Redis实例安全的重要步骤。Redis提供了多种身份验证机制,包括简单的密码认证和更复杂的ACL(访问控制列表)机制。以下是详细的配置步骤和代码示例。 1. 使用简单密码认证 配置文件配置 在Redis配置文件 (redis.conf) 中设置 requirepass 选项。 # redis.conf requirepass yourpassword 命令行参数配置 启动Redis服务器时通过命令行参数设置: redis-server --requirepass


Python 的内置函数 dict
IMPYLH2025/10/26

Python 内建函数列表 > Python 的内置函数 dict Python 的内置函数 dict 是用于创建字典对象的构造函数。字典是 Python 中最常用的数据结构之一,它采用键值对(key-value pairs)的形式存储数据,提供高效的数据查询能力。 class dict(**kwarg): ''' 类型转换为 dict :param kwarg: 键值对 :return: 转换为 dict 后的值 ''' 示例 person


AWS EKS 计算资源自动扩缩之Karpenter[AWS 海外区]
thinktik2025/10/24

Karpenter是一个为Kubernetes构建的开源自动扩缩容项目。它提高了Kubernetes应用程序的可用性,而无需手动或过度配置计算资源。 Karpenter旨在通过观察不可调度的Pod的聚合资源请求并做出启动和终止节点的决策,以最大限度地减少调度延迟,从而在几秒钟内(而不是几分钟)提供合适的计算资源来满足您的应用程序的需求。 karpenter可以替代传统的cluster-autoscaler,我们可以参考karpenter进行安装,选择Migrating from Cluster

首页编辑器站点地图

Copyright © 2025 聚合阅读

License: CC BY-SA 4.0