From 50c55283a0b752d07939f561e70fdb4bd390724c Mon Sep 17 00:00:00 2001 From: zhangsheng Date: Thu, 13 Mar 2025 15:12:03 +0800 Subject: [PATCH] add tcp client --- MyTcpClient.cpp | 104 +++++++++++ MyTcpClient.h | 43 +++++ qss.qrc | 5 + qss/soft.css | 453 ++++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 605 insertions(+) create mode 100644 MyTcpClient.cpp create mode 100644 MyTcpClient.h create mode 100644 qss.qrc create mode 100644 qss/soft.css diff --git a/MyTcpClient.cpp b/MyTcpClient.cpp new file mode 100644 index 0000000..eac07c6 --- /dev/null +++ b/MyTcpClient.cpp @@ -0,0 +1,104 @@ +#include "MyTcpClient.h" +#include +#include "data_config.h" + +MyTcpClient::MyTcpClient(QObject *parent) : QObject(parent), shouldReconnect(true) { + socket = new QTcpSocket(this); + + connect(socket, &QTcpSocket::connected, this, &MyTcpClient::onConnected); + connect(socket, &QTcpSocket::readyRead, this, &MyTcpClient::onReadyRead); + connect(socket, &QTcpSocket::disconnected, this, &MyTcpClient::onDisconnected); + //connect(socket, &QTcpSocket::errorOccurred, this, &MyTcpClient::onErrorOccurred); + + // 连接失败后,定时尝试重连 + connect(&reconnectTimer, &QTimer::timeout, this, &MyTcpClient::onReconnect); + reconnectTimer.setInterval(5000); // 5秒重连一次 + + // 发送心跳包 + //connect(&heartbeatTimer, &QTimer::timeout, this, &MyTcpClient::sendHeartbeat); + //heartbeatTimer.setInterval(10000); // 10秒发送一次心跳 +} + +MyTcpClient::~MyTcpClient() { + shouldReconnect = false; + if (socket) { + socket->disconnectFromHost(); + socket->deleteLater(); + } +} + +void MyTcpClient::connectToServer(const QString &host, quint16 port) { + serverHost = host; + serverPort = port; + if (socket->state() == QAbstractSocket::ConnectedState) { + qDebug() << "Already connected!"; + return; + } + qDebug() << "Connecting to" << host << ":" << port; + socket->connectToHost(host, port); + if (!socket->waitForConnected()) { + qDebug() << "Connection failed!"; + return; + } +} + +int MyTcpClient::sendData(char*data,qint64 len) { + + qint64 bytesWritten = socket->write(data, len); + socket->waitForBytesWritten(); + return bytesWritten; +} +void MyTcpClient::waitForRead() { + socket->waitForReadyRead(); +} +void MyTcpClient::disconnectFromServer() { + shouldReconnect = false; // 停止自动重连 + reconnectTimer.stop(); + heartbeatTimer.stop(); + socket->disconnectFromHost(); +} + +void MyTcpClient::onConnected() { + qDebug() << "Connected to server!"; + emit connected(); + + reconnectTimer.stop(); // 连接成功,停止自动重连 + heartbeatTimer.start(); // 开始发送心跳包 +} + +void MyTcpClient::onReadyRead() { + QByteArray data = socket->readAll(); + emit dataReceived(data); +} + +void MyTcpClient::onDisconnected() { + qDebug() << "Disconnected from server!"; + emit disconnected(); + + if (shouldReconnect) { + qDebug() << "Attempting to reconnect in 5 seconds..."; + reconnectTimer.start(); // 触发自动重连 + heartbeatTimer.stop(); // 断开后停止心跳 + } +} + +void MyTcpClient::onErrorOccurred(QAbstractSocket::SocketError socketError) { + Q_UNUSED(socketError) + qDebug() << "Socket error:" << socket->errorString(); + emit errorOccurred(socket->errorString()); +} + +void MyTcpClient::onReconnect() { + if (socket->state() == QAbstractSocket::UnconnectedState) { + qDebug() << "Reconnecting to" << serverHost << ":" << serverPort; + socket->connectToHost(serverHost, serverPort); + } +} + +void MyTcpClient::sendHeartbeat() { + if (socket->state() == QAbstractSocket::ConnectedState) { + QByteArray heartbeat = "HEARTBEAT"; // 这里可以换成协议规定的心跳包 + socket->write(heartbeat); + qDebug() << "Sent heartbeat to server."; + } +} diff --git a/MyTcpClient.h b/MyTcpClient.h new file mode 100644 index 0000000..35a3377 --- /dev/null +++ b/MyTcpClient.h @@ -0,0 +1,43 @@ +#ifndef MYTCPCLIENT_H +#define MYTCPCLIENT_H + +#include +#include +#include + +class MyTcpClient : public QObject { + Q_OBJECT + +public: + explicit MyTcpClient(QObject *parent = nullptr); + ~MyTcpClient(); + + void connectToServer(const QString &host, quint16 port); + int sendData(char* data,qint64 len); + void waitForRead(); + void disconnectFromServer(); + +signals: + void connected(); + void disconnected(); + void dataReceived(const QByteArray &data); + void errorOccurred(const QString &errorMsg); + +private slots: + void onConnected(); + void onReadyRead(); + void onDisconnected(); + void onErrorOccurred(QAbstractSocket::SocketError socketError); + void onReconnect(); + void sendHeartbeat(); + +private: + QTcpSocket *socket; + QTimer reconnectTimer; // 自动重连定时器 + QTimer heartbeatTimer; // 心跳包定时器 + QString serverHost; + quint16 serverPort; + bool shouldReconnect; // 标记是否需要重连 +}; + +#endif // MYTCPCLIENT_H diff --git a/qss.qrc b/qss.qrc new file mode 100644 index 0000000..553a4a8 --- /dev/null +++ b/qss.qrc @@ -0,0 +1,5 @@ + + + qss/soft.css + + diff --git a/qss/soft.css b/qss/soft.css new file mode 100644 index 0000000..6817833 --- /dev/null +++ b/qss/soft.css @@ -0,0 +1,453 @@ + +QWidget[flag="title"]{ + /*border-image:url(:/image/title.png)*/ + background-color:#f2f4f7;background-image:url(:/image/title.png);background-position:left;background-repeat:no-repeat; +} +QWidget[flag="body"]{ + border-style:none; + border-radius:0px; + padding:5px; + color:#f2f4f7; + background:#f2f4f7; +} +QLabel{ + background-color: transparent; /* 按钮背景颜色 */ + border-radius:0px; + color:#484848; + background:none; + border-style:none; +} +QPushButton { + background-color: #f2f4f7; /* 按钮背景颜色 */ + color: black; /* 文字颜色 */ + border: 1px solid #2980b9; /* 边框颜色 */ + border-radius: 6px; /* 圆角 */ + padding: 5px 10px; /* 内边距 */ + font: 12px "黑体"; /* 字体 */ +} + +QPushButton:hover { + background-color: #1f5188; /* 悬停时背景颜色 */ + border-color: #1f6690; /* 悬停时边框颜色 */ + color: white; /* 悬停时文字颜色 */ +} + +QPushButton:pressed { + background-color: #1f6690; /* 按下时背景颜色 */ + border-color: #0f3d5a; /* 按下时边框颜色 */ + color: white; /* 悬停时文字颜色 */ +} +QComboBox { + background-color: white; /* 背景颜色 */ + color: #484848; /* 文字颜色 */ + border: 1px solid #2980b9; /* 边框颜色 */ + border-radius: 6px; /* 圆角 */ + padding: 5px 10px; /* 内边距 */ + font: 12px "黑体"; /* 字体 */ + min-width: 100px; /* 最小宽度 */ +} + +/* 下拉箭头 */ +/*QComboBox::down-arrow { + width: 14px; + height: 14px; +}*/ +/* 鼠标悬停 */ +QComboBox:hover { + background-color: #2980b9; + color: white; /* 文字颜色 */ +} +/* 按下时 */ +QComboBox:pressed { + background-color: #1f6690; +} +/* 禁用状态 */ +QComboBox:disabled { + background-color: #7f8c8d; + color: #bdc3c7; + border-color: #95a5a6; +} +/* 下拉列表整体 */ +QComboBox QAbstractItemView { + background-color: white; /* 背景颜色 */ + border: 0px solid #34495e; + color: #1f1010; + selection-background-color: #1f5188; /* 选中项背景颜色 */ + selection-color: white; /* 选中项文字颜色 */ +} +/* 下拉列表项 */ +QComboBox QAbstractItemView::item { + padding: 5px; + color: #484848; + height: 15px; /* 设置每一项的高度 */ +} +QComboBox QAbstractItemView::item:hover{ + background-color:#409CE1; + color:#1b1e23; +} +QComboBox QAbstractItemView::item:selected{ + background-color:#409CE1; + color:#ffffff; +} + + +QMenuBar{ + background-color: white; /* 设置MenuBar的背景颜色 */ + color: #1f1010; /* 设置MenuBar的字体颜色 */ +} +QStatusBar{ + background-color: white; /* 设置StatusBar的背景颜色 */ + color: #1f1010; /* 设置StatusBar的字体颜色 */ +} +QMenuBar::item { + /* 这里可以设置每个菜单项的样式 */ + spacing: 3px; /* 设置菜单项之间的间距 */ + padding: 1px 10px; /* 设置菜单项的填充 */ + background-color: white; /* 设置菜单项的背景颜色 */ + color: #1f1010; /* 设置菜单项的字体颜色 */ +} + +QMenuBar::item:selected { + /* 设置选中菜单项的样式 */ + background-color: #1f5188; /* 选中时背景颜色 */ + color: white; /* 选中时字体颜色 */ +} +QMenu { + background-color: white; /* 背景颜色 */ + border: 0px solid #666; + color: #1f1010; /* 字体颜色 */ +} + +QMenu::item { + padding: 6px 20px; + background-color: white; +} + +QMenu::item:selected { /* 悬停 */ + background-color: #1f5188; + color: white; +} + +QMenu::separator { + height: 1px; + background: white; + margin: 5px; +} +QGroupBox { + border: 1px solid #2980b9; /* 边框颜色 */ + border-radius: 6px; /* 圆角 */ + margin-top: 10px; /* 标题上方的间距 */ + font: 12px "黑体"; /* 设置字体 */ + color: white; /* 标题颜色 */ + background-color: #f2f4f7; /* 背景颜色 */ +} + +/* 标题文本的背景 */ +QGroupBox::title { + subcontrol-origin: margin; + subcontrol-position: top left; /* 让标题靠左 */ + padding: 2px 10px; /* 调整标题的内边距 */ + background-color: #2980b9; /* 标题背景颜色 */ + color: white; /* 标题文字颜色 */ + border-radius: 1px; +} +/* 整个选项卡区域的背景 */ +QTabWidget::pane { + border: 1px solid #2980b9; /* 边框颜色 */ + border-radius: 6px; /* 圆角 */ + background-color: #f2f4f7; /* 背景颜色 */ +} + +/* 选项卡(未选中状态) */ +QTabBar::tab { + background: #f2f4f7; /* 选项卡背景 */ + color: #484848; /* 文字颜色 */ + border: 1px solid #2980b9; /* 选项卡边框 */ + border-radius: 4px; /* 选项卡圆角 */ + padding: 5px 15px; /* 内边距 */ + margin: 2px; /* 选项卡之间的间距 */ +} + +/* 选中的选项卡 */ +QTabBar::tab:selected { + background: #2980b9; + color: white; + font-weight: bold; +} + +/* 悬停时的选项卡 */ +QTabBar::tab:hover { + background: #2980b9; + color: white; +} + +/* 选项卡栏的位置(靠左) */ +QTabWidget::tab-bar { + alignment: left; +} +QDoubleSpinBox { + border: 1px solid #2980b9; /* 边框颜色 */ + border-radius: 6px; /* 圆角 */ + background-color: white; /* 背景颜色 */ + color: #484848; /* 文字颜色 */ + padding: 2px 8px; /* 内边距 */ + font: 12px "Arial"; +} + +/* 失去焦点时的样式 */ +QDoubleSpinBox:!focus { + border: 1px solid #1f6690; +} + +/* 鼠标悬停时 */ +QDoubleSpinBox:hover { + border: 1px solid #1abc9c; +} + +/* 增加/减少按钮 */ +QDoubleSpinBox::up-button, QDoubleSpinBox::down-button { + width: 16px; + border: none; + background-color: #3498db; /* 按钮背景色 */ + color: white; + border-radius: 4px; +} + +/* 鼠标悬停时按钮变色 */ +QDoubleSpinBox::up-button:hover, QDoubleSpinBox::down-button:hover { + background-color: #1f6690; +} + +/* 按钮按下时 */ +QDoubleSpinBox::up-button:pressed, QDoubleSpinBox::down-button:pressed { + background-color: #145a7a; +} + +/* 上增按钮 */ +QDoubleSpinBox::up-arrow { + image: url(:/icons/up_arrow.png); /* 自定义上箭头图片 */ + width: 10px; + height: 10px; +} + +/* 下减按钮 */ +QDoubleSpinBox::down-arrow { + image: url(:/icons/down_arrow.png); /* 自定义下箭头图片 */ + width: 10px; + height: 10px; +} + +/* 禁用状态 */ +QDoubleSpinBox:disabled { + background-color: #cac4c3; + color: black; + border: 1px solid #95a5a6; +} +/* QCheckBox 默认样式 */ +QCheckBox { + spacing: 5px; /* 复选框与文本的间距 */ + color: #484848; /* 文本颜色 */ + font-size: 14px; +} + +/* 鼠标悬停 */ +QCheckBox:hover { + color: #1abc9c; +} + +/* 复选框(未选中状态) */ +QCheckBox::indicator { + width: 16px; + height: 16px; + border-radius: 4px; + background-color: #f2f4f7; + border: 1px solid #2980b9; +} + +/* 复选框(选中状态) */ +QCheckBox::indicator:checked { + background-color: #2980b9; + border: 1px solid #1abc9c; + image: url(:/icons/checked.png); /* 自定义选中图标 */ +} + +/* 复选框(未选中但鼠标悬停) */ +QCheckBox::indicator:hover { + background-color: #1f6690; +} + +/* 复选框(禁用状态) */ +QCheckBox:disabled { + color: #7f8c8d; +} +QCheckBox::indicator:disabled { + background-color: #7f8c8d; + border: 2px solid #95a5a6; +} +QLineEdit { + border: 1px solid #2980b9; /* 边框颜色 */ + border-radius: 6px; /* 圆角 */ + background-color: white; /* 背景色 */ + color: #484848; /* 文字颜色 */ + font-size: 14px; + padding: 4px 10px; /* 内边距 */ +} + +/* 当 QLineEdit 处于焦点状态(被选中) */ +QLineEdit:focus { + border: 1px solid #1abc9c; /* 选中时的边框颜色 */ + background-color: white; /* 选中时的背景色 */ +} + +/* 禁用状态 */ +QLineEdit:disabled { + background-color: white; + color: #484848; + border: 0px solid #95a5a6; +} + +/* 只读状态 */ +QLineEdit:read-only { + background-color: #cac4c3; + color: #cccccc; + border: 2px solid #555555; +} + +/* 提示文本(Placeholder)颜色 */ +QLineEdit::placeholder { + color: #95a5a6; + font-style: italic; +} + +/* 清除按钮(如果 `setClearButtonEnabled(true)` 被调用) */ +QLineEdit::clear-button { + image: url(:/icons/clear.png); + width: 16px; + height: 16px; + margin-right: 5px; +} +QSpinBox { + border: 1px solid #2980b9; /* 边框颜色 */ + border-radius: 6px; /* 圆角 */ + background-color: white; /* 背景色 */ + color: #484848; /* 文字颜色 */ + font-size: 14px; + padding: 2px 8px; /* 内边距 */ +} + +/* 选中状态 */ +QSpinBox:focus { + border: 2px solid #1abc9c; /* 选中时的边框颜色 */ + background-color: white; /* 选中时的背景色 */ +} + +/* 禁用状态 */ +QSpinBox:disabled { + background-color: #cac4c3; + color: #484848; + border: 1px solid #95a5a6; +} + +/* 只读状态 */ +QSpinBox:read-only { + background-color: #3b3b3b; + color: #cccccc; + border: 1px solid #555555; +} + +/* 上下调节按钮 */ +QSpinBox::up-button, QSpinBox::down-button { + width: 16px; + background-color: #2980b9; /* 按钮背景 */ + border: none; + border-radius: 3px; +} + +/* 上调节按钮 */ +QSpinBox::up-button { + subcontrol-origin: border; + subcontrol-position: top right; /* 右上角 */ + image: url(:/icons/up_arrow.png); /* 上箭头图标 */ + margin: 2px; +} + +/* 下调节按钮 */ +QSpinBox::down-button { + subcontrol-origin: border; + subcontrol-position: bottom right; /* 右下角 */ + image: url(:/icons/down_arrow.png); /* 下箭头图标 */ + margin: 2px; +} + +/* 按钮鼠标悬停 */ +QSpinBox::up-button:hover, QSpinBox::down-button:hover { + background-color: #1abc9c; +} + +/* 按钮禁用状态 */ +QSpinBox::up-button:disabled, QSpinBox::down-button:disabled { + background-color: #7f8c8d; + image: none; +} + +/* 箭头禁用状态 */ +QSpinBox::up-arrow:disabled, QSpinBox::down-arrow:disabled { + image: none; +} +QRadioButton { + color: #484848; /* 文字颜色 */ + font-size: 14px; + spacing: 8px; /* 文字与圆圈的间距 */ +} + +/* 未选中时的圆圈 */ +QRadioButton::indicator { + width: 16px; + height: 16px; + border-radius: 8px; /* 让它变成圆形 */ + border: 1px solid #2980b9; /* 圆圈边框 */ + background-color: transparent; +} + +/* 选中状态 */ +QRadioButton::indicator:checked { + background-color: #2980b9; /* 选中时的内部颜色 */ + border: 1px solid #1abc9c; /* 选中时的边框颜色 */ +} + +/* 禁用状态 */ +QRadioButton:disabled { + color: #7f8c8d; +} + +QRadioButton::indicator:disabled { + border: 1px solid #7f8c8d; + background-color: #95a5a6; +} + +QTableView QLineEdit,QTableView QComboBox,QTableView QSpinBox,QTableView QDoubleSpinBox,QTableView QDateEdit,QTableView QTimeEdit,QTableView QDateTimeEdit{ +border:2px groove gray; +color: #484848; /* 文字颜色 */ +/*border-radius:10px; +border-radius: 15px;*/ +} + +QTableView QLineEdit:focus,QTableView QComboBox:focus,QTableView QSpinBox:focus,QTableView QDoubleSpinBox:focus,QTableView QDateEdit:focus,QTableView QTimeEdit:focus,QTableView QDateTimeEdit:focus{ +border-width:0px; +border-radius:0px; +} + + +QLineEdit,QTextEdit,QPlainTextEdit,QSpinBox,QDoubleSpinBox,QComboBox,QDateEdit,QTimeEdit,QDateTimeEdit{ +color:#1b1e23; +background:#ffffff; +} + + +QPalette{background:#f2f4f7;}*{outline:0px;color:#f2f4f7;} + +QGraphicsView{ + border:1px solid #f2f4f7; + qproperty-backgroundBrush:#f2f4f7; +} +